Condividi tramite


Errori e avvisi di Auto-Il parallelizzare

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 abilita 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 basso, il compilatore non parallelizza automaticamente questo ciclo. Tuttavia, se l'utente sa che u sarà sempre un valore alto, è possibile parallelizzarlo. Per abilitare la parallelizzazione automatica, specificare #pragma loop(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 alternativa pragma __pragma(loop(hint_parallel(n))).

Alcuni cicli non possono essere parallelizzati dal compilatore, anche se lo si desidera. Di seguito è riportato 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 rilevato, il compilatore può generare un messaggio di diagnostica che spiega perché non è possibile parallelizzare il 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 di output tra le due opzioni /Qvec-report (livello di segnalazione parallelizzazione automatica). /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 su codici motivo e messaggi, vedere Messaggi di vettorizzazione e parallelizzazione.

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 fa riferimento alle istruzioni SSE2, AVX e AVX2 nei processori Intel o AMD o alle istruzioni NEON nei processori ARM, a seconda dell'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. Per confrontare le prestazioni del codice con la vettorizzazione applicata, è possibile usare #pragma loop(no_vector) per disabilitare la vettorizzazione di cicli specificati.

#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 alternativa pragma __pragma(loop(no_vector)).

Come per la parallelizzazione automatica, è possibile specificare l'opzione della riga di comando /Qvec-report (livello di segnalazione vettorizzazione automatica) per restituire solo i cicli correttamente vettorizzati, /Qvec-report:1, o tutti i cicli indipendentemente dall'esito della vettorizzazione, /Qvec-report:2).

Per altre informazioni su codici motivo e messaggi, vedere Messaggi di vettorizzazione e parallelizzazione.

Per un esempio pratico del funzionamento della vettorizzazione, vedere il blog del progetto Austin parte 2 di 6 relativo a come sfogliare le pagine

Vedere anche

Riferimenti

loop

/Qpar (Parallelizzazione automatica)

/Qvec-report (livello di segnalazione parallelizzazione automatica)

/Qvec-report (livello di segnalazione vettorizzazione automatica)

Altre risorse

Parallel Programming in Native Code

Messaggi di vettorizzazione e parallelizzazione