Megosztás:


Automatikus párhuzamosítás és automatikus vektorizálás

Az Auto-Parallelizer és az Auto-Vectorizer automatikus teljesítményjavulást biztosít a kód hurkainak.

Automatikus párhuzamosító

A /Qpar fordítókapcsoló lehetővé teszi a ciklusok automatikus párhuzamosítását a kódban. Ha a meglévő kód módosítása nélkül adja meg ezt a jelzőt, a fordító kiértékeli a kódot, hogy megtalálja azokat a hurkokat, amelyek kihasználhatják a párhuzamosítás előnyeit. Mivel olyan hurkokat találhat, amelyek nem végeznek sok munkát, és ezért nem részesülnek a párhuzamosítás előnyeiből, és mivel minden szükségtelen párhuzamosítás lehetővé teheti egy szálkészlet létrehozását, további szinkronizálást vagy más feldolgozást, ami inkább lassítaná, semmint javítaná a teljesítményt, a fordító ezért óvatosan választja ki azokat a hurkokat, amelyeket párhuzamosít. Vegyük például az alábbi példát, amelyben a hurok felső határa nem ismert fordításkor:

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

Mivel u lehet egy kis érték, a fordító nem fogja automatikusan párhuzamosítani ezt a hurkot. Azonban előfordulhat, hogy mégis szeretné párhuzamosítani, mert tudja, hogy a u mindig nagy lesz. Az automatikus párhuzamosítás engedélyezéséhez adja meg #pragma hurok(hint_parallel(n)) értéket, ahol n a párhuzamossá tenni kívánt szálak száma. Az alábbi példában a fordító megkísérli párhuzamossá tenni a hurkot 8 szálon.

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

Az összes pragma-direktívához hasonlóan az alternatív pragma szintaxis __pragma(loop(hint_parallel(n))) is támogatott.

Vannak olyan hurkok, amelyeket a fordító nem tud párhuzamosítani, még akkor sem, ha szeretné. Íme egy példa:

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

A függvény upper_bound() minden híváskor megváltozhat. Mivel a felső határ nem ismert, a fordító képes diagnosztikai üzenetet kibocsátani, amely elmagyarázza, hogy miért nem tudja párhuzamossá tenni ezt a hurkot. Az alábbi példa egy párhuzamosítható hurkot, egy nem párhuzamos hurkot, a parancssorban használni kívánt fordító szintaxist és az egyes parancssori beállítások fordítókimenetét mutatja be:

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;
    }
}

Fordítás a következő paranccsal:

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

ezt a kimenetet adja eredményként:

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

Fordítás a következő paranccsal:

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

ezt a kimenetet adja eredményként:

--- 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'

Észrevegye a különbséget a kimenetben a két különböző /Qpar-report (Auto-Parallelizer jelentési szint) opció között. /Qpar-report:1 a párhuzamosító üzeneteket csak a sikeresen párhuzamosított hurkok esetében adja ki. /Qpar-report:2 sikeres és sikertelen ciklus-párhuzamosításokhoz tartozó párhuzamosítási üzeneteket is kimenetet ad.

Az okkódokkal és üzenetekkel kapcsolatos további információkért lásd: Vectorizer és Parallelizer Messages.

Automatikus vektorizáló

Az Auto-Vectorizer elemzi a kódban lévő hurkokat, és a célszámítógép vektorregisztrálóit és utasításait használja a végrehajtásukhoz, ha van rá lehetőség. Ez javíthatja a kód teljesítményét. A fordító az SSE2, AVX és AVX2 utasításokat célozza meg Intel- vagy AMD-processzorokban, illetve a NEON-utasításokat ARM-processzorokon a /arch kapcsolónak megfelelően.

Az automatikus vektorizáló a kapcsoló által /arch megadotttól eltérő utasításokat hozhat létre. Ezeket az utasításokat futásidejű ellenőrzés védi, hogy a kód továbbra is megfelelően fusson. Például, amikor a /arch:SSE2-t fordítja, SSE4.2 utasítások kibocsáthatók. A futtatókörnyezet ellenőrzése ellenőrzi, hogy az SSE4.2 elérhető-e a célprocesszoron, és a ciklus nem SSE4.2-es verziójára ugrik, ha a processzor nem támogatja ezeket az utasításokat.

Alapértelmezés szerint az automatikus vektorizáló engedélyezve van. Ha össze szeretné hasonlítani a kód teljesítményét vektorizálás alatt, #pragma hurok (no_vector) használatával letilthatja az adott hurkok vektorizálását.

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

Az összes pragma-direktívához hasonlóan az alternatív pragma szintaxis __pragma(loop(no_vector)) is támogatott.

Az automatikus párhuzamosítóhoz hasonlóan megadhatja a /Qvec-report (Auto-Vectorizer Reporting Level) parancssori kapcsolót is, amellyel csak a vektorizált hurkok (/Qvec-report:1 vagy sikeres és sikertelen vektorizált hurkok/Qvec-report:2) jelentésére van lehetőség.

Az okkódokkal és üzenetekkel kapcsolatos további információkért lásd: Vectorizer és Parallelizer Messages.

A vektorizáló gyakorlati működését bemutató példáért lásd a Project Austin 2. részét a 6: Page Curlingről

Lásd még

hurok
Párhuzamos programozás natív kódban
/Qpar (Automatikus Párhuzamosító)
/Qpar-report (Automatikus párhuzamosító jelentési szint)
/Qvec-report (Automatikus vetektoralási jelentési szint)
Vektorizáló és párhuzamosító üzenetek