#parallel ile for
Açıklaması
şöyle. Blok içindeki kodu işleyen N tane thread başlatılır.
#pragma omp parallel spawns a group of threads, while #pragma omp for divides loop iterations between the spawned threads.
Şöyle
yaparız.
#pragma omp parallel
{
#pragma omp for
for (int i=0;i<NX;i++)
{
...
}
#pragma omp for
for (int i=1;i<NX-1;i++)
{
...
}
}
#parallel ile threadprivate
Şöyle
yaparız
static int dataVersion;
data_t& GetData()
{
static data_t *d = NULL;
#pragma omp threadprivate(d); // !!!
if (d && d->myDataVersion != dataVersion) {
delete d;
d = nullptr;
}
if (!d) {
d = new data_t();
d->myDataVersion = dataVersion;
}
return *d;
}
#parallel ile section
Şöyle
yaparız.Her thread bir section kodunu çalıştırır.
#pragma omp parallel sections
{
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());/* Executes in thread 1 */
}
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());/* Executes in thread 2 */
}
}
Çıktı olarak şunu alırız
id = 0,
id = 1,
Çalışma şekli
şöyledir. N tane thread başlatılır. Sadece iki tanesi çalışır, diğerleri bekler. Thread 1 kısa sürede biter. Thread 2 biraz daha uzun çalışır. Tüm thread'ler sections sonundaki bariyerdel (* işareti) buluşurlar.
[ sections ]
Thread 0: -------< section 1 >---->*------
Thread 1: -------< section 2 >*------
Thread 2: ------------------------>*------
... *
Thread N-1: ---------------------->*------
#parallel ile single
Örnek
Şöyle
yaparız. Single producer her nesneyi kuyruğa koyar. task'lar ise kuyruktan okurlar.
#pragma omp parallel
{
#pragma omp single
{
for (auto x : stl_container)
{
#pragma omp task
{
// Do something with x, e.g.
compute(x);
}
}
}
}
Çalışma şekli
şöyledir.
+--+-->[ task queue ]--+
| | |
| | +-----------+
| | |
Thread 0: --< single >-| v |-----
Thread 1: -------->|< foo() >|-----
Thread 2: -------->|< bar() >|-----
Örnek
Şöyle
yaparız.
#pragma omp parallel num_threads(2)
{
#pragma omp single
QuickSort(arr, 0, arr.length, cuttoff);
}
#parallel ile thread sayısı
Şöyle
yaparız.
#pragma omp parallel num_threads (10)
{
...
}
Şöyle
yaparız.
#pragma omp parallel num_threads(3)
#pragma omp for
{
...
}
#parallel ile reduction
Söz dizimi
şöyle.
reduction(operation:var)
Açıklaması
şöyle.
Note that reduction variables are private and their intermediate values (i.e. the value they hold before the reduction at the end of the parallel region) are only partial and not very useful.
Örnek
Şöyle
yaparız.
#include <iostream>
#include <omp.h>
struct dbl_int {
double val;
int idx;
};
const dbl_int& max( const dbl_int& a, const dbl_int& b) {
return a.val > b.val ? a : b;
}
#pragma omp declare reduction( maxVal: dbl_int: omp_out=max( omp_out, omp_in ) )
int main() {
dbl_int di = { -100., -1 };
#pragma omp parallel num_threads( 10 ) reduction( maxVal: di )
{
di.val = omp_get_thread_num() % 7;
di.idx = omp_get_thread_num();
}
return 0;
}
Örnek
Şöyle
yaparız.
//g++ -O3 -Wall foo.cpp -fopenmp
#pragma omp parallel for reduction(+:sum)
for(int i = 0 ; i < 2000000000; i++)
sum += i%11;
#parallel İçinde critical + barrier
Şöyle
yaparız.
#pragma omp parallel
{
...
#pragma omp critical(iteration) //Scope için mutex koy
{
iteration++; //Bir değişkeni artır
}
...
#pragma omp critical(reduction) //If için mutex koy
if (...)
{
...
}
#pragma omp barrier //Tüm thread'lerin bitmesini bekle
...
}
#pragma İçinde dynamic
Şöyle
yaparız. Paralel kodun 4 thread tarafından çalıştırılmasını sağlar.
#pragma omp parallel
{
#pragma omp for schedule(dynamic,4)
for (i = 0; i < N; i++)
{
...
}
...
}
İptal Etme
OpenMP 2'de iptal etmek yapıları yok. OpenMP 4 ile geldi. Şöyle
yaparız.