Condividi tramite


Parallelizzazione automatica e vettorizzazione automatica

Le funzioni di parallelizzazione automatica e vettorizzazione automatica sono progettate per fornire miglioramenti automatici nelle prestazioni per i cicli nel codice.

Parallelizzazione automatica

L'opzione del compilatore /Qpar consente la parallelizzazione automatica dei cicli nel codice. Quando si specifica questo flag senza modificare il codice esistente, il compilatore valuta il codice per trovare i cicli per i quali potrebbe essere utile la parallelizzazione. Il compilatore adotta un approccio conservativo nella selezione dei cicli da parallelizzare perché potrebbe trovare cicli per i quali questa funzione non è utile oppure perché tutte le parallelizzazioni non necessarie possono comportare la generazione di un pool di thread, una sincronizzazione aggiuntiva o altri tipi di elaborazione che rallentano le prestazioni invece di migliorarle. Ad esempio, prendere in considerazione il seguente esempio in cui il limite superiore del ciclo non è noto in fase di compilazione:

void loop_test(int u) {
   for (int i=0; i<u; ++i)
      A[i] = B[i] * C[i];
}

Poiché u potrebbe essere un valore ridotto, il compilatore non parallelizzerà automaticamente questo ciclo. Tuttavia, se l'utente sa che u sarà sempre un valore alto, è possibile parallelizzarlo. Per abilitare la parallelizzazione automatica, specificare #pragma ciclo (hint_parallel(n)), dove n è il numero di thread da parallelizzare. Nel seguente esempio, il compilatore tenta di parallelizzare il in 8 thread.

void loop_test(int u) {
#pragma loop(hint_parallel(8))
   for (int i=0; i<u; ++i)
      A[i] = B[i] * C[i];
}

Come per tutte le direttive pragma, è supportata anche la sintassi __pragma(loop(hint_parallel(n))) pragma alternativa.

Esistono alcuni cicli che il compilatore non può parallelizzare anche se lo si vuole. Ecco un esempio:

#pragma loop(hint_parallel(8))
for (int i=0; i<upper_bound(); ++i)
    A[i] = B[i] * C[i];

La funzione upper_bound() può cambiare ogni volta che viene chiamata. Poiché il limite superiore non può essere noto, il compilatore può generare un messaggio di diagnostica che spiega perché non può parallelizzare questo ciclo. Nel seguente esempio viene mostrato un ciclo parallelizzabile, un ciclo non parallelizzabile, la sintassi del compilatore da usare al prompt dei comandi e l'output del compilatore per ciascuna opzione della riga di comando:

int A[1000];
void test() {
#pragma loop(hint_parallel(0))
    for (int i=0; i<1000; ++i) {
        A[i] = A[i] + 1;
    }

    for (int i=1000; i<2000; ++i) {
        A[i] = A[i] + 1;
    }
}

La compilazione con il seguente comando:

cl d:\myproject\mylooptest.cpp /O2 /Qpar /Qpar-report:1

restituisce questo output:

--- Analyzing function: void __cdecl test(void)
d:\myproject\mytest.cpp(4) : loop parallelized

La compilazione con il seguente comando:

cl d:\myproject\mylooptest.cpp /O2 /Qpar /Qpar-report:2

restituisce questo output:

--- Analyzing function: void __cdecl test(void)
d:\myproject\mytest.cpp(4) : loop parallelized
d:\myproject\mytest.cpp(4) : loop not parallelized due to reason '1008'

Si noti la differenza nell'output tra le due diverse opzioni /Qpar-report (livello di report parallelizzatore automatico). /Qpar-report:1 restituisce i messaggi di parallelizzazione solo per i cicli correttamente parallelizzati. /Qpar-report:2 restituisce i messaggi di parallelizzazione sia per le parallelizzazioni dei cicli riuscite che per quelle non riuscite.

Per altre informazioni sui codici motivo e i messaggi, vedere Vectorizer and Parallelizer Messages.For more information about reason codes and messages, see Vectorizer and Parallelizer Messages.

Vettorizzazione automatica

La vettorizzazione automatica analizza i cicli nel codice e usa i registri e le istruzioni del vettore nel computer di destinazione per eseguirli, se possibile. Questa funzione può migliorare le prestazioni del codice. Il compilatore è destinato alle istruzioni S edizione Standard 2, AVX e AVX2 nei processori Intel o AMD o alle istruzioni NEON sui processori ARM, in base all'opzione /arch.

La vettorizzazione automatica può generare istruzioni diverse da quelle specificate dall'opzione /arch. Queste istruzioni sono protette da un controllo di runtime per verificare il corretto funzionamento del codice. Ad esempio, quando si compila /arch:SSE2, è possibile che vengano generate istruzioni SSE4.2. Un controllo di runtime verifica che SSE4.2 sia disponibile nel processore di destinazione e passa a una versione non SSE4.2 del ciclo se il processore non supporta tali istruzioni.

Per impostazione predefinita, la vettorizzazione automatica è abilitata. Se si desidera confrontare le prestazioni del codice in base alla vettorizzazione, è possibile usare #pragma loop (no_vector) per disabilitare la vettorizzazione di qualsiasi ciclo specificato.

#pragma loop(no_vector)
for (int i = 0; i < 1000; ++i)
   A[i] = B[i] + C[i];

Come per tutte le direttive pragma, è supportata anche la sintassi __pragma(loop(no_vector)) pragma alternativa.

Come per il parallelizzatore automatico, è possibile specificare l'opzione della riga di comando /Qvec-report (livello di report vettorializzatore automatico) per segnalare solo/Qvec-report:1 cicli vettorializzati correttamente, o entrambi i cicli vettorizzati correttamente e senza esito positivo)./Qvec-report:2

Per altre informazioni sui codici motivo e i messaggi, vedere Vectorizer and Parallelizer Messages.For more information about reason codes and messages, see Vectorizer and Parallelizer Messages.

Per un esempio che mostra il funzionamento del vettore in pratica, vedere Project Austin Part 2 of 6: Page Curling

Vedi anche

loop
Programmazione parallela in codice nativo
/Qpar (parallelizzazione automatica)
/Qvec/report (livello di segnalazione parallelizzazione automatica)
/Qvec/report (livello di segnalazione vettorizzazione automatica)
Messaggi di vettorizzazione e parallelizzazione