OpenMP etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
OpenMP etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

15 Şubat 2021 Pazartesi

OpenMP Critical Section

Giriş 
Mutex ile aynı anlama gelir. Söz dizimi şöyle
#pragma omp critical(name)
Açıklaması şöyle,
The critical section names are global to the entire program (regardless of module boundaries). So if you have a critical section by the same name in multiple modules, not two of them can be executed at the same time. If the name is omitted, a default name is assumed.
Örnek
Eğer paralel kod içinde mutex kullanmak istersek şöyle yaparız.
#pragma omp critical
{
    //code only be written from a thread
}
Örnek
Şöyle yaparız
#include <iostream>

int main(int argc, char** argv)
{
  int someVar = 0;

  #pragma omp parallel for
  for (int i = 0; i < 1000; i++)
  {
    #pragma omp critical
    ++someVar;
  }

  std::cout << someVar << std::endl;

  return 0;
}
Eğer OpenMP yerine normal C++ kullanmak istersek şöyle yaparız.
#include <iostream>
#include <mutex>

int main(int argc, char** argv)
{
  int someVar = 0;
  std::mutex someVar_mutex;

  #pragma omp parallel for
  for (int i = 0; i < 1000; i++)
  {
    std::lock_guard<std::mutex> lock(someVar_mutex);
    ++someVar;
  }

  std::cout << someVar << std::endl;

  return 0;
}

19 Aralık 2018 Çarşamba

OpenMP parallel for - Döngüyü Paralelleştirir

Giriş
Şu satırı dahil ederiz.
#include <omp.h>
#parallel ve #parallel for Fakı Nedir
#pragma omp parallel blok içindeki aynı kodu N tane thread tarafından çalıştırır. Şeklen şöyledir

#pragma omp parallel for döngüyü N tane thread'e böler. Şeklen şöyledir. Burada chunk olarak 1 veriliyor. Dolayısıyla her thread 1 tane eleman işleyip, 4 tane eleman atlıyor.



#parallel for
N'e kadar olan döngü şöyle paralelleştirilir. Her thread döngünün belli bir kısmını çalıştırır. Örneğin ilk thread 1-100 , ikinci thread 101 - 200 arası vs. gibi.
#pragma omp parallel for
for(int i = 0; i < N; i++)
{
    ...
}
#parallel for ile C++11
Eğer v random access iterator sağlıyorsa şöyle yaparız.
#pragma omp parallel for
for (it = v.begin(); it < v.end(); it++)
{
   ...
}
#parallel for ile thread sayısı
Şöyle yaparız.
#pragma omp parallel for num_threads(2)
for (i = 0; i < N; i++) 
{
  ...
}   
#parallel for içinde critical
Şöyle yaparız.
#pragma omp parallel for
for (int i = 20; i < 1000; i++) 
{
  ...
  #pragma omp critical
  {
    ...
  }

}
#parallel for içinde atomic
Şöyle yaparız.
int iteration = 0;
#pragma omp parallel for 
for (int i = 0; i < num_voxels; i++)
{
  ...
  #pragma omp atomic
  iteration++;
  ...  

}

4 Haziran 2018 Pazartesi

OpenMP

Giriş
Bu kütüphaneyi kullanmak için şu satır dahil edilir.
#include <omp.h>
Birçok C++ derleyicisi kendi OpenMP gerçekleştirimini sağlıyor. Intel, GCC bunlar arasında
Visual Studio 2012'de şöyle yapılır.
Project > Properties sağ tıklanır. Configuration Properties > C/C++ > Language altında "Open MP Support" = Yes yapılır. Bu ayar ile derleyiciye "/openmp" seçeneği belirtilir.

Pragmalar
Flush
Şöyle yaparız.
bool foo = false;
#pragma omp flush (foo)
Paralel Kod
OpenMP parallel yazısına taşıdım.

Critical
OpenMP Critical yazısına taşıdım

Master
Şöyle yaparız. omp single ile karşılaştırılabilir.
#pragma omp master
{
  ...
}
Paralel For
OpenMP parallel for yazısına taşıdım.

Parallel For + Schedule
Tam ne işe yaradığını anlamadım.

dynamic seçeneği için şöyle yaparız.
#pragma omp parallel for schedule(dynamic)
for(int i=0; i<n; i++){
  ...
}
runtime seçenepi için şöyle yaparız.
#pragma omp parallel for private(i) schedule(runtime)
for ( i=0; i<n; ++i ) {
{ 
  ...
}
Parallel For + nowait
Her paralel for döngüsü sonunda thread'lerin birbirini beklediği görünmez bir bariyer bulunur. Eğer bu olmasın istersek şöyle yaparız.
#pragma omp parallel
{

  #pragma omp for nowait
  for(int i=0; i<100; i++) {
    ...
  }
  #pragma omp for nowait
  for(int i=0; i<100; i++) {
    ...
  }
}
Paralel For + private ve shared değişkenler
Şöyle yapılabilir.
unsigned int i,j;

#pragma omp parallel for private (j) shared(i) 
for (i=0;i<NX;i++)
{
...
}
Metodlar
Süre Ölçümü
şöyle yapılabilir.
double tbeg = omp_get_wtime();
...
double time = omp_get_wtime() - tbeg;
cout<<"finish in "<<time<<" seconds"<<endl;



11 Mayıs 2018 Cuma

OpenMP parallel - Blok içindeki kodu işleyen N tane thread başlatılır

#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.