Bagikan melalui


Paralelisasi Otomatis dan Vektorisasi Otomatis

Auto-Parallelizer dan Auto-Vectorizer dirancang untuk memberikan keuntungan performa otomatis untuk perulangan dalam kode Anda.

Paralelizer Otomatis

Sakelar kompilator /Qpar memungkinkan paralelisasi otomatis perulangan dalam kode Anda. Saat Anda menentukan bendera ini tanpa mengubah kode yang ada, pengkompilasi mengevaluasi kode untuk menemukan perulangan yang mungkin mendapat manfaat dari paralelisasi. Karena mungkin menemukan perulangan yang tidak melakukan banyak pekerjaan dan oleh karena itu tidak akan mendapat manfaat dari paralelisasi, dan karena setiap paralelisasi yang tidak perlu dapat membangkitkan pemijahan kumpulan utas, sinkronisasi ekstra, atau pemrosesan lain yang akan cenderung memperlambat performa alih-alih meningkatkannya, kompilator konservatif dalam memilih perulangan yang diparalelkan. Misalnya, pertimbangkan contoh berikut di mana batas atas perulangan tidak diketahui pada waktu kompilasi:

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

Karena u bisa menjadi nilai kecil, pengkompilasi tidak akan secara otomatis menyejajarkan perulangan ini. Namun, Anda mungkin masih ingin itu diparalelkan karena Anda tahu itu u akan selalu besar. Untuk mengaktifkan paralelisasi otomatis, tentukan perulangan #pragma(hint_parallel(n)), di mana n adalah jumlah utas yang akan diparalelkan di seluruhnya. Dalam contoh berikut, pengkompilasi akan mencoba untuk menyejajarkan perulangan di 8 utas.

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

Seperti semua arahan pragma, sintaksis __pragma(loop(hint_parallel(n))) pragma alternatif juga didukung.

Ada beberapa perulangan yang tidak dapat diparalelkan kompilator bahkan jika Anda menginginkannya. Berikut contohnya:

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

Fungsi upper_bound() mungkin berubah setiap kali dipanggil. Karena batas atas tidak dapat diketahui, pengkompilasi dapat memancarkan pesan diagnostik yang menjelaskan mengapa tidak dapat menyejajarkan perulangan ini. Contoh berikut menunjukkan perulangan yang dapat diparalelkan, perulangan yang tidak dapat diparalelkan, sintaks pengkompilasi yang akan digunakan pada prompt perintah, dan output pengkompilasi untuk setiap opsi baris perintah:

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

Mengkompilasi dengan menggunakan perintah ini:

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

menghasilkan output ini:

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

Mengkompilasi dengan menggunakan perintah ini:

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

menghasilkan output ini:

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

Perhatikan perbedaan output antara dua opsi /Qpar-report (Auto-Parallelizer Reporting Level) yang berbeda. /Qpar-report:1 menghasilkan pesan paralelizer hanya untuk perulangan yang berhasil diparalelkan. /Qpar-report:2 menghasilkan pesan paralelizer untuk paralelisasi perulangan yang berhasil dan tidak berhasil.

Untuk informasi selengkapnya tentang kode dan pesan alasan, lihat Pesan Vektorizer dan Paralelizer.

Auto-Vectorizer

Auto-Vectorizer menganalisis perulangan dalam kode Anda, dan menggunakan daftar vektor dan instruksi pada komputer target untuk mengeksekusinya, jika bisa. Ini dapat meningkatkan performa kode Anda. Pengompilasi menargetkan instruksi SSE2, AVX, dan AVX2 dalam prosesor Intel atau AMD, atau instruksi NEON pada prosesor ARM, sesuai dengan sakelar /arch .

Vektorizer Otomatis dapat menghasilkan instruksi yang berbeda dari yang ditentukan oleh sakelar /arch . Instruksi ini dijaga oleh pemeriksaan runtime untuk memastikan bahwa kode masih berjalan dengan benar. Misalnya, saat Anda mengkompilasi /arch:SSE2, instruksi SSE4.2 dapat dipancarkan. Pemeriksaan runtime memverifikasi bahwa SSE4.2 tersedia pada prosesor target dan melompat ke perulangan versi non-SSE4.2 jika prosesor tidak mendukung instruksi tersebut.

Secara default, Auto-Vectorizer diaktifkan. Jika Anda ingin membandingkan performa kode Anda di bawah vektorisasi, Anda dapat menggunakan perulangan #pragma(no_vector) untuk menonaktifkan vektorisasi perulangan tertentu.

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

Seperti semua arahan pragma, sintaksis __pragma(loop(no_vector)) pragma alternatif juga didukung.

Seperti halnya opsi baris perintah /Qvec-report (Auto-Vectorizer Reporting Level) untuk melaporkan perulangan yang berhasil diverifikasi saja—/Qvec-report:1—atau perulangan yang berhasil dan tidak berhasil diverifikasi—/Qvec-report:2).

Untuk informasi selengkapnya tentang kode dan pesan alasan, lihat Pesan Vektorizer dan Paralelizer.

Untuk contoh yang menunjukkan cara kerja vektorizer dalam praktiknya, lihat Proyek Austin Bagian 2 dari 6: Penguraian Halaman

Lihat juga

Loop
Pemrograman Paralel dalam Kode Asli
/Qpar (Auto-Parallelizer)
/Qpar-report (Tingkat Pelaporan Paralelizer Otomatis)
/Qvec-report (Tingkat Pelaporan Vektorizer Otomatis)
Pesan Vektorizer dan Paralelizer