Perbedaan antara #pragma omp parallel dan #pragma omp parallel for
Saya baru OpenMP
dan saya telah mencoba menjalankan program yang menambahkan dua array menggunakan OpenMP. Dalam tutorial OpenMP, saya telah belajar bahwa kita perlu menggunakan #pragma omp parallel untuk saat menggunakan OpenMP pada loop for . Tetapi saya juga mencoba hal yang sama dengan #pragma omp parallel dan itu juga memberi saya hasil yang benar. Di bawah ini adalah potongan kode dari apa yang ingin saya sampaikan.
#pragma omp parallel for
{
for(int i=0;i<n;i++)
{
c[i]=a[i]+b[i];
}
}
dan
#pragma omp parallel
{
for(int i=0;i<n;i++)
{
c[i]=a[i]+b[i];
}
}
Apa perbedaan antara keduanya?
Jawaban
Itu
#pragma omp parallel
:
akan membuat parallel region
dengan tim threads
, di mana setiap utas akan mengeksekusi seluruh blok kode yang parallel region
disertakan.
Dari OpenMP 5.1 seseorang dapat membaca deskripsi yang lebih formal:
Ketika sebuah utas menemukan konstruksi paralel , tim utas dibuat untuk mengeksekusi wilayah paralel (..). Utas yang mengalami konstruksi paralel menjadi utas utama tim baru, dengan nomor utas nol selama wilayah paralel baru. Semua utas di tim baru, termasuk utas utama, menjalankan wilayah tersebut. Setelah tim dibuat, jumlah utas dalam tim tetap konstan selama wilayah paralel tersebut.
Itu:
#pragma omp parallel for
akan membuat parallel region
(seperti yang dijelaskan sebelumnya), dan ke threads
wilayah itu iterasi loop yang dilingkupinya akan ditetapkan, menggunakan default chunk size
, dan default schedule
yang biasanya static
. Ingatlah, bagaimanapun, bahwa default schedule
mungkin berbeda di antara penerapan konkret yang berbeda dari OpenMP
standar.
Dari OpenMP 5.1 Anda dapat membaca deskripsi yang lebih formal:
Konstruksi worksharing-loop menentukan bahwa iterasi dari satu atau lebih loop terkait akan dieksekusi secara paralel oleh thread dalam tim dalam konteks tugas implisitnya. Iterasi didistribusikan di seluruh utas yang sudah ada di tim yang menjalankan wilayah paralel yang mengikat wilayah loop berbagi kerja .
Selain itu ,
Konstruksi loop paralel adalah jalan pintas untuk menentukan konstruksi paralel yang berisi konstruksi loop dengan satu atau lebih loop terkait dan tidak ada pernyataan lain.
Atau secara informal, #pragma omp parallel for
merupakan kombinasi konstruktor #pragma omp parallel
dengan #pragma omp for
. Dalam kasus Anda, ini berarti:
#pragma omp parallel for
{
for(int i=0;i<n;i++)
{
c[i]=a[i]+b[i];
}
}
secara semantik, dan logis, sama dengan:
#pragma omp parallel
{
#pragma omp for
for(int i=0;i<n;i++)
{
c[i]=a[i]+b[i];
}
}
TL; DR: Dalam contoh Anda, dengan #pragma omp parallel for
loop akan diparalelkan di antara utas ( yaitu, iterasi loop akan dibagi di antara utas), sedangkan dengan #pragma omp parallel
semua utas akan mengeksekusi (secara paralel) semua iterasi loop.
Untuk membuatnya lebih ilustratif, dengan 4
utas tersebut #pragma omp parallel
, akan menghasilkan sesuatu seperti:

sedangkan #pragma omp parallel for
dengan a chunk_size=1
dan statis schedule
akan menghasilkan sesuatu seperti:

Dari segi kode, loop akan diubah menjadi sesuatu yang secara logis mirip dengan:
for(int i=omp_get_thread_num(); i < n; i+=omp_get_num_threads())
{
c[i]=a[i]+b[i];
}
dimana omp_get_thread_num ()
Rutin omp_get_thread_num mengembalikan nomor thread, dalam tim saat ini, dari thread pemanggil.
dan omp_get_num_threads ()
Mengembalikan jumlah utas di tim saat ini. Di bagian berurutan dari program omp_get_num_threads mengembalikan 1.
atau dengan kata lain for(int i = THREAD_ID; i < n; i += TOTAL_THREADS)
,. Dengan rentang THREAD_ID
dari 0
hingga TOTAL_THREADS - 1
, dan TOTAL_THREADS
mewakili jumlah total utas tim yang dibuat di wilayah paralel.
Saya telah belajar bahwa kita perlu menggunakan paralel #pragma omp untuk sementara menggunakan OpenMP pada perulangan for. Tetapi saya juga mencoba hal yang sama dengan #pragma omp parallel dan itu juga memberi saya hasil yang benar.
Ini memberi Anda hasil yang sama, karena dalam kode Anda:
c[i]=a[i]+b[i];
array a
dan array b
hanya dibaca, dan array c[i]
adalah satu-satunya yang diperbarui, dan nilainya tidak bergantung pada berapa kali iterasi i
akan dijalankan. Namun demikian, dengan #pragma omp parallel for
setiap utas akan memperbarui sendiri i
, sedangkan #pragma omp parallel
utas akan memperbarui yang sama i
, sehingga menimpa nilai satu sama lain.
Sekarang coba lakukan hal yang sama dengan kode berikut:
#pragma omp parallel for
{
for(int i=0;i<n;i++)
{
c[i]= c[i] + a[i] + b[i];
}
}
dan
#pragma omp for
{
for(int i=0;i<n;i++)
{
c[i] = c[i] + a[i] + b[i];
}
}
Anda akan segera melihat perbedaannya.
Dalam kasus kedua, loop tidak diparalelkan. Yakni, seluruh loop dijalankan di setiap utas . Umumnya, apa pun yang ada di dalam wilayah paralel dijalankan oleh semua utas.
Anda juga dapat memparalelkan loop di region paralel yang sudah ada sebagai berikut:
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < n; i++)
c[i] = a[i] + b[i];
}