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 bisa menemukan perulangan yang tidak melakukan banyak pekerjaan dan karenanya tidak akan mendapat manfaat dari paralelisasi, serta karena setiap paralelisasi yang tidak perlu dapat membangkitkan pembentukan kumpulan utas, sinkronisasi ekstra, atau pemrosesan lain yang cenderung memperlambat performa daripada meningkatkannya, kompilator bersikap 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 dijalankan secara paralel karena Anda tahu bahwa 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 berusaha untuk memparalelkan 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 direktif 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 dari paralelizer untuk pengulangan paralel yang berhasil maupun tidak.

Untuk informasi selengkapnya tentang kode alasan dan pesan, lihat Pesan-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 pada prosesor Intel atau AMD, atau instruksi NEON pada prosesor ARM, sesuai dengan opsi /arch.

Pemvektor Otomatis dapat menghasilkan instruksi yang berbeda daripada 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 direktif pragma, sintaksis alternatif __pragma(loop(no_vector)) pragma juga didukung.

Seperti halnya dengan Auto-Parallelizer, Anda dapat menentukan opsi baris perintah /Qvec-report (Auto-Vectorizer Reporting Level) untuk melaporkan perulangan yang berhasil divektorisasi saja—/Qvec-report:1—atau perulangan yang berhasil dan tidak berhasil divektorisasi—/Qvec-report:2).

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

Untuk contoh yang menunjukkan cara kerja vektorisasi dalam praktiknya, lihat Proyek Austin Bagian 2 dari 6: Efek Lipatan 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