Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Autoparallelliserare och autovektoriserare är utformade för att ge automatiska prestandavinster för loopar i koden.
Automatisk parallellisering
Kompilatorväxeln /Qpar möjliggör automatisk parallellisering av loopar i koden. När du anger den här flaggan utan att ändra din befintliga kod utvärderar kompilatorn koden för att hitta loopar som kan dra nytta av parallellisering. Eftersom det kan hitta loopar som inte utför mycket arbete och därför inte drar nytta av parallellisering, och eftersom varje onödig parallellisering kan skapa en trådpool, extra synkronisering eller annan bearbetning som tenderar att försämra prestanda i stället för att förbättra den, är kompilatorn konservativ när den väljer de slingor som den parallelliserar. Tänk till exempel på följande exempel där loopens övre gräns inte är känd vid kompileringstillfället:
void loop_test(int u) {
for (int i=0; i<u; ++i)
A[i] = B[i] * C[i];
}
Eftersom u det kan vara ett litet värde parallelliserar kompilatorn inte automatiskt den här loopen. Men du kanske fortfarande vill att u ska parallelliseras eftersom du vet att det alltid kommer att vara stort. Om du vill aktivera den automatiska parallelliseringen anger du #pragma loop(hint_parallel(n)), där n är antalet trådar som ska parallelliseras över. I följande exempel försöker kompilatorn parallellisera loopen mellan 8 trådar.
void loop_test(int u) {
#pragma loop(hint_parallel(8))
for (int i=0; i<u; ++i)
A[i] = B[i] * C[i];
}
Precis som med alla pragma-direktiv stöds även den alternativa pragmasyntaxen __pragma(loop(hint_parallel(n))) .
Det finns vissa loopar som kompilatorn inte kan parallellisera även om du vill. Här är ett exempel:
#pragma loop(hint_parallel(8))
for (int i=0; i<upper_bound(); ++i)
A[i] = B[i] * C[i];
Funktionen upper_bound() kan ändras varje gång den anropas. Eftersom den övre gränsen inte kan vara känd kan kompilatorn generera ett diagnostikmeddelande som förklarar varför den inte kan parallellisera den här loopen. I följande exempel visas en loop som kan parallelliseras, en loop som inte kan parallelliseras, kompilatorsyntaxen som ska användas i kommandotolken och kompilatorns utdata för varje kommandoradsalternativ:
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;
}
}
Kompilera med hjälp av det här kommandot:
cl d:\myproject\mylooptest.cpp /O2 /Qpar /Qpar-report:1
ger följande utdata:
--- Analyzing function: void __cdecl test(void)
d:\myproject\mytest.cpp(4) : loop parallelized
Kompilera med hjälp av det här kommandot:
cl d:\myproject\mylooptest.cpp /O2 /Qpar /Qpar-report:2
ger följande utdata:
--- 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'
Observera skillnaden i utdata mellan de två olika /Qpar-rapportalternativen (Auto-Parallelizer Reporting Level).
/Qpar-report:1 ger endast ut meddelanden om parallelliseringen för loopar som har parallelliserats framgångsrikt.
/Qpar-report:2 matar ut parallelliserarmeddelanden för både lyckade och misslyckade loopparallelliseringar.
Mer information om orsakskoder och meddelanden finns i Vectorizer and Parallelizer Messages (Vektoriserare och parallelliseringsmeddelanden).
Automatisk vektoriserare
Autovektoriseraren analyserar loopar i koden och använder vektorregister och instruktioner på måldatorn för att köra dem, om det kan. Detta kan förbättra kodens prestanda. Kompilatorn riktar in sig på SSE2-, AVX- och AVX2-instruktionerna i Intel- eller AMD-processorer, eller NEON-instruktionerna på ARM-processorer, enligt /arch-växeln .
Autovektoriseraren kan generera andra instruktioner än vad som anges av växeln /arch . De här anvisningarna skyddas av en körningstidkontroll för att se till att koden fortfarande körs korrekt. När du till exempel kompilerar /arch:SSE2kan SSE4.2-instruktioner genereras. En körningskontroll verifierar att SSE4.2 är tillgängligt på målprocessorn och hoppar till en icke-SSE4.2-version av loopen om processorn inte stöder dessa instruktioner.
Som standard är autovektoriseraren aktiverad. Om du vill jämföra kodens prestanda under vektorisering kan du använda #pragma-loop (no_vector) för att inaktivera vektorisering av en viss loop.
#pragma loop(no_vector)
for (int i = 0; i < 1000; ++i)
A[i] = B[i] + C[i];
Precis som med alla pragma-direktiv stöds även den alternativa pragmasyntaxen __pragma(loop(no_vector)) .
Precis som med autoparallelliseraren kan du ange kommandoradsalternativet /Qvec-report (Auto-Vectorizer Reporting Level) för att rapportera antingen endast vektoriserade loopar –/Qvec-report:1 eller både lyckade och misslyckade vektoriserade loopar )./Qvec-report:2
Mer information om orsakskoder och meddelanden finns i Vectorizer and Parallelizer Messages (Vektoriserare och parallelliseringsmeddelanden).
Ett exempel som visar hur vektoriseraren fungerar i praktiken finns i Project Austin del 2 av 6: Page Curling
Se även
ögla
Parallell programmering i intern kod
/Qpar (automatisk parallellisering)
/Qpar-rapport (rapporteringsnivå för automatisk parallellisering)
/Qvec-report (rapporteringsnivå för automatisk vektoriserare)
Vektoriserare och parallelliserarmeddelanden