La clausola ordered
funziona così: diversi thread eseguono contemporaneamente fino incontrano regione ordered
, che viene poi eseguito in sequenza nello stesso ordine come sarebbe ottenere eseguito in un loop seriale. Ciò consente ancora un certo grado di concorrenza, soprattutto se la sezione di codice all'esterno della regione ordered
ha un tempo di esecuzione sostanziale.
Non vi è alcun motivo particolare per utilizzare la pianificazione dynamic
anziché la pianificazione static
con piccole dimensioni del blocco. Tutto dipende dalla struttura del codice. Poiché ordered
introduce la dipendenza tra i thread, se utilizzato con schedule(static)
con dimensioni di blocco predefinite, il secondo thread dovrebbe attendere che il primo completi tutte le iterazioni, quindi il terzo thread dovrebbe attendere che il secondo termini le iterazioni (e quindi anche per il primo), e così via. Si potrebbe facilmente visualizzare con 3 fili e 9 iterazioni (3 per thread):
tid List of Timeline
iterations
0 0,1,2 ==o==o==o
1 3,4,5 ==.......o==o==o
2 6,7,8 ==..............o==o==o
=
mostra che il filo viene eseguito codice in parallelo. o
è quando il thread sta eseguendo la regione ordered
. .
è il thread inattivo, in attesa del suo turno per eseguire la regione ordered
. Con schedule(static,1)
accadrebbe quanto segue:
tid List of Timeline
iterations
0 0,3,6 ==o==o==o
1 1,4,7 ==.o==o==o
2 2,5,8 ==..o==o==o
Credo che la differenza in entrambi i casi è più che evidente. Con schedule(dynamic)
le immagini sopra diventerebbero più o meno casuali in quanto l'elenco delle iterazioni assegnate a ciascun thread non è deterministico. Inoltre, aggiungerebbe un ulteriore sovraccarico. È utile solo se la quantità di calcolo è diversa per ogni iterazione e richiede molto più tempo per eseguire il calcolo rispetto all'overhead aggiunto dell'utilizzo della pianificazione dinamica.
Non preoccuparti dell'iterazione con il numero più basso. Di solito viene gestito nel primo thread del team per essere pronto per eseguire il codice.
Ottima risposta Hristo! Tutto chiaro ora, grazie! –
@ Cookie503, notare che se la dimensione del blocco è troppo piccola, la memorizzazione nella cache potrebbe risultare meno utile a causa della località di dati persi. Ciò potrebbe danneggiare la tua performance molto peggio della serializzazione implicita. Sperimenta diverse dimensioni del blocco fino a ottenere la migliore accelerazione. Usa i loop 'ordered' saggiamente e se possibile li eludono, anche se questo porta ad un maggiore footprint di memoria - ad es. (dato il tuo esempio particolare) dovrebbe essere usato un semplice array preallocato (o un altro contenitore ad accesso casuale thread-safe) invece di un vettore: 'arr [i] = i;' –