http://blog.csdn.net/bendanban/article/details/6303282
在上一節中我們講的是一個常用的并行化編程方法(for的并行化),其實它只是并行化編程的一個特例,只是它的地位較高,或者說它比其它并行化更重要。在本節中我們將討論一般的并行區域編程。
并行區域的編譯指導語句一般格式
一般格式:#pragma omp parallel [clause[clause]…]{…}
其中{…}中為每個線程都執行的部分,在parallel后面可以跟隨一些指導子句,例如:threadprivate、copyin等,本節中將以一些實例來依次講解這些語句的作用。
時刻記住,主線程就是0號線程,這個與for不同,另外private、firstprivate、lastprivate是for并行的東西最好不要拿來比較,盡管我在本文里比較了,但是我還是感覺有些頭痛啊。
例子實例
例1 不帶指導子句的并行程序
#pragma omp parallel指示它下面的一對大括號內的程序復制執行threads個數次。默默人情況下,所有并行區域中的變量是共享的,所以一定要謹防數據競爭的發生。
#include
#include "omp.h"
int main(int argc, char* argv[])


{
#pragma omp parallel
for (int i = 0; i < 2; i++)

{
printf("Hello World! i = %d, Thread Num = %d/n", i, omp_get_thread_num());
}
return 0;
}

圖1、例1的執行結果
例1的執行結果可以看出四個線程分別執行了一遍#pragma omp parallel下面的語句,想想一下如果使用#pragma omp parallel for會是什么樣的結果。
例2 使用threadprivate子句
此命令表示所有并行線程使用指定變量為各自私有的,能被定義為各線程私有變量的變量只能是靜態變量和全局變量。看下面的程序,希望你能發現,其實#pragma omp threadprivate()是可以單獨使用的。
說明一下:被定義為threadprivate的變量對于每個線程永遠是活的,你在任何時候再次重新啟動各線程時,前面并行時最后得到的變量值仍然保留他的值,如果你用private代替threadprivate,那么你重新啟動各線程時,變量的值仍然為0。如果你不初始化要聲明為private的變量,那么在串行程序中,你就不能再沒有任何賦值的情況下使用它,否則會引起異常的(VS2010)。而且private不能單獨像threadprivate那樣定義某個變量。
如果你使用另外#pragma omp threadprivate(var),那么var必須是靜態變量或者全局變量,如過你在并行開始之前并沒有初始化賦值,那么每個線程中默認var的值為0.如果你賦了初值,那么每個線程中var的初值都是你賦的初始值。其中主線程就是0號線程。如果你使用了#pragma omp private(var),那么var并不會賦初值,即使你在并行之前賦了初值。想想原先#pragma omp parallel for 的firstprivate就知道了,呵呵。在#pragma omp parallel中可以使用lastprivate,但是不能使用lastprivate,使用firstprivate(var)后,串行部分的var并不是并行時0號線程的var值,它仍未你原先賦的初值。是不是很繞啊?呵呵,你可以這樣理解,使用firstprivate和private的并行都不是純真的聯合主線程的編號。這樣就混不了了。
#include
#include "omp.h"
int sum = 0;
#pragma omp threadprivate(sum)
int main(int argc, char* argv[])


{
#pragma omp parallel

{
sum += omp_get_thread_num();
printf("parallel sum = %d; thread num = %d/n", sum, omp_get_thread_num());
}
printf("/nserial sum = %d; thread num = %d/n/n", sum, omp_get_thread_num());
#pragma omp parallel
printf("parallel sum = %d; thread num = %d/n", sum, omp_get_thread_num());
return 0;
}

圖2、例2執行結果
threadprivate指定了sum這個變量屬于每個線程,每個線程都有自己的sum變量,各個線程結束后他們的sum變量并沒有注銷,在此啊執行時,他們各自的sum值還保持原值。
例3 使用copyin
指定主線程的值拷貝到各線程中去,下面的例子中,sum是每個線程獨有的,并且初始值都是0,main中第一行代碼將0號線程的sum值賦為100,其它線程的sum值并沒有變。
#include <stdio.h>
#include "omp.h"
int sum;
#pragma omp threadprivate(sum)
int main(int argc, char* argv[])


{
sum = 100;
#pragma omp parallel copyin(sum)

{
sum += omp_get_thread_num();
printf("parallel sum = %d; thread num = %d/n", sum, omp_get_thread_num());
}
printf("/nserial sum = %d; thread num = %d/n/n", sum, omp_get_thread_num());
#pragma omp parallel
printf("parallel sum = %d; thread num = %d/n", sum, omp_get_thread_num());
return 0;
}

圖3、例3的執行結果

圖4、例3中將copyin(sum)刪除后的執行結果
通過以上圖3、4可以看出copyin的用處是初始化各個線程中自己私有的sum變量。實際上定義sum為全局量時的初始值就是原sum值(如果不使用copyin的話)。
我想了想threadprivate和private以及firstprivate的區別。寫出來大家討論下。
1、threadprivate,限制變量為每個線程私有。被限制的變量必須具有全局特性,他的生命周期是整個程序。
2、private,可以限制變量為每個線程私有,但是他的生命周期是一次啟動并行計算。
3、firstprivate,可以將穿行程序中的初值帶進每個線程,變量為每個線程私有。生命周期與private相同。
4、還有個lastprivate的問題,他并不能在區域并行中使用。
大家實驗把。。。