Kapat
Anasayfa 367 0

C++ Threading Kullanmak İçin 5 Neden

Gelecek 10 – 15 yilda, her iki yilda bir islemci hizinin iki katina cikacagini soyleyen Moore Kanunu’nun sonuna
gelebiliriz. Teoride, bu soylemi gerceklestirebilmek icin transistorler cok kucuk parcalara ayriliyorlar,
hatta suanda bile ureticiler ve gelistiriciler, bir instruction ile birden cok veri islemine olanak saglayan
farkli paralellestirme ( vectorization gibi ) formlari kullanma ve islemciler uzerine birden fazla cekirdek
ekleme konusu uzerine calisiyorlar.

Birden fazla islemcinin sadece tek bir cekirdege sahip oldugu durumda, C++ gibi eski diller ile, daha fazla
cekirdek kullanan kod yazmak daha zordur. Bu sebepten dolayi, bazi farkli metotlar dusunulmustur. Bu makalede,
bu farkli metotlardan iki tanesine bakacagiz.

5 Neden?
Asagida daha fazla cekirdek kullanan kod yazmak icin anahtar sebepler mevcut.

– İşlem suresini hizlandirmak
– İşlemler arasi etkilesim oluşturmak
– Verileri ve I/O işlemlerini ortuşturmek
– Daha az kaynak kullanmak
– Paylaşimi kolaylaştirmak

Eger islemler birden fazla ayri hesaplamalara ayrilabilir ve birden fazla cekirdek ile bir CPU uzerinde calisabilir,
indigenmis calisma zamanina gecebilirlerse, islem suresi hizlandirilabilir. Uygulama GUI tabanli ise ve yogun hesaplama
ozellikleri iceriyorsa, bir arka plan thread’i icerisinde gereksinimlerin yuku cok fazla yer kaplamasa dahi, GUI
donmalari olusabilir. Ayni risk, disk veya network tabanli buyuk I/O islemleri icin de gecerlidir. Bir islemi birden
fazla cekirdege dagitilip, bir thread icerisinde yapilan islemler ile mukayese edildiginde, kaynak kullaniminin azaldigi
gozlemlenmektedir.

Kendi kendinize bir multithread kod yaziyorsaniz, thread yaratma ve yonetme islemleri zor olabilir. Zamanlamadan
dolayi debug surecinde gozlemlenemeyen fakat urun icerisinde ortaya cikan bir suru problem olacaktir.

Thread Olmadan Threading

Sonuc olarak hem thread kullanip hem de olasi zafiyetlerden korunmak istiyoruz. Bir kac kutuphane bize bu yetenegi
sunmaktadir: bunlardan en populerleri Intel TBB ve acik kaynak OpenMP kutuphaneleridir. Her iki kutuphane de C++ ve
Fortran dillerini desteklemektedir, hatta OpenMP C dili ile de kullanilabilir.

Intel TBB

Veri yapilari ve algoritmalar iceren TBB, is yukunu birden fazla cekirdekte dengelemek icin template yapilarini kullanir.
Bir cekirdek gorevini bitirip serbest kaldiktan sonra, TBB is yukunu cekirdeklere paylastirirken bu anda yeni bir duzenleme
yaparak dinamik bir sekilde davranir. OpenMP’nin aksine TBB, herhangi bir C++ derleyicisi ile calisabilir ve ozel bir
destege ihtiyac duymaz. Sadece Intel TBB paylasimli kutuphaneleri koda eklenmelidir, ardindan TBB namespace’i ile tum yapilara
erisilebilir.

TBB’nin paralel calisan for, do, while, sort ve baska bir takim yapilari vardir. Ayrica, es zamanli queue, vector ve hashmap
gibi veri yapilarina ve calisma sureci boyunca baska bir process tarafindan mudahele edilmemesi garantilenen, dusuk seviyeli
memory al******** ve atomic operasyonlara da sahiptir.

Asagidaki ornekte, getValue fonksiyon cagrisi ile kullanilan buyuk verilerin parcalanmasi icin TBB kutuphanesine ait
parallel_for kullanilarak islem yuku azaltilip performans artiriliyor.

// Hold our outputs
std::vector outputs{ kMaxValues };

// Uses parallel for loop with a C++11 lambda to perform mapping into outputs
tbb::parallel_for(size_t(0), kMaxValues, [ &outputs ]( size_t i ) { outputs = getValue(i); } );

// Do reduction
double output=0.0;
for(double v: outputs) { output += v;}

OpenMP

OpenMP, kodun parallellige ihtiyaci oldugu anda, kole threadleri calistiran bir lider thread’e sahip mantikla calisir.
Intel TBB kutuphanesinin calismasinin aksine, derleyicinin OpenMP direktiflerinin harici olarak implement etmeye ihtiyaci
vardir. Microsoft Visual Studio C++ 2013 icin en guncel OpenMP, 4.0 versiyonudur. Ayni zamanda 2.0 versiyonunu da destekler.

OpenMP’i kod icerisinde kullanabilmek icin, derleyici icerisindeki kutuphaneyi aktif duruma getirmek gerekir. Bunun icin
paralellestirme yapilmak istenilen kisimlara pragmalar eklenir. Ek olarak omp.h header dosyasini ekleyerek belli fonksiyonlari
cagirmak gereklidir. Bunlar olasi thread sayisini belirleyen omp_set_num_threads() fonksiyonu ve calisma zamaninda dinamik thread
sayisina izin veren omp_set_dynamic() fonksiyonudur.

#define THREADS 8

#ifdef _OPENMP
omp_set_num_threads(THREADS);
omp_set_dynamic(THREADS);
#endif

Asagidaki kodda, ’pragma omp parallel for’ ifadesi dongunun paralel calismasi icin kullanilmistir.

vector<node>* routes[num_cities – 1];

#pragma omp parallel for
for (int i = 0; i < num_cities – 1; ++i) {
vector<node>* search_nodes = new vector<node>();
routes = search_nodes;

int dist = find_route(map, city_locs, i, *search_nodes);
cost += dist;
}

Critical section alanlari icin #pragma omp critical pragmasi kullanilabilir. OpenMP, paralel ve paralel olmayan parcalar
arasinda veri paylasiminda oldukca iyidir. Bir verinin, bir thread icin veya paylasmak icin gizli olmasi veya olmamasi
saglanabilir. Bu ozellik main thread icerisinde degiskeninin farkli bir sekilde ilklendirilmesi ile yapilir.

Sonuç

Sonuç olarak, C++ kodunuzun performasini threading ile artirmak ve olabilecek bir takim karisikliklardan ve risklerden
uzak durmak istiyorsaniz Intel TBB veya OpenMP’den herhangi birini deneyebilirsiniz. Her iki kutuphanede ucretsizdir.

[Toplam: 0   Ortalama: 0/5]
Burak Eti

Burak Eti {Burak Eti}