日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
OpenMP中的數(shù)據(jù)處理子句

10.1.1 private子句

創(chuàng)新互聯(lián)建站于2013年開始,先為茫崖等服務(wù)建站,茫崖等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為茫崖企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

private子句用于將一個(gè)或多個(gè)變量聲明成線程私有的變量,變量聲明成私有變量后,指定每個(gè)線程都有它自己的變量私有副本,其他線程無法訪問私有副本。即使在并行區(qū)域外有同名的共享變量,共享變量在并行區(qū)域內(nèi)不起任何作用,并且并行區(qū)域內(nèi)不會操作到外面的共享變量。

private子句的用法格式如下:

private(list)

下面便是一個(gè)使用private子句的代碼例子:

 
 
 
  1.  int k = 100; 
  2. #pragma omp parallel for private(k) 
  3.          for ( k=0; k < 10; k++) 
  4.          { 
  5.                    printf("k=%d/n", k); 
  6.          } 
  7.   
  8.          printf("last k=%d/n", k); 
  9. 上面程序執(zhí)行后打印的結(jié)果如下: 
  10. k=6 
  11. k=7 
  12. k=8 
  13. k=9 
  14. k=0 
  15. k=1 
  16. k=2 
  17. k=3 
  18. k=4 
  19. k=5 
  20. last k=100 

從打印結(jié)果可以看出,for循環(huán)前的變量k和循環(huán)區(qū)域內(nèi)的變量k其實(shí)是兩個(gè)不同的變量。

用private子句聲明的私有變量的初始值在并行區(qū)域的入口處是未定義的,它并不會繼承同名共享變量的值。

出現(xiàn)在reduction子句中的參數(shù)不能出現(xiàn)在private子句中。

10.1.2 firstprivate子句

private聲明的私有變量不能繼承同名變量的值,但實(shí)際情況中有時(shí)需要繼承原有共享變量的值,OpenMP提供了firstprivate子句來實(shí)現(xiàn)這個(gè)功能。

先看一下以下的代碼例子

 
 
 
  1. int k = 100; 
  2. #pragma omp parallel for firstprivate(k) 
  3.          for ( i=0; i < 4; i++) 
  4.          { 
  5.                    k+=i; 
  6.                    printf("k=%d/n",k); 
  7.          } 
  8.   
  9.          printf("last k=%d/n", k); 
  10.   

上面代碼執(zhí)行后打印結(jié)果如下:

k=100

k=101

k=103

k=102

last k=100

從打印結(jié)果可以看出,并行區(qū)域內(nèi)的私有變量k繼承了外面共享變量k的值100作為初始值,并且在退出并行區(qū)域后,共享變量k的值保持為100未變。

10.1.3 lastprivate子句

有時(shí)在并行區(qū)域內(nèi)的私有變量的值經(jīng)過計(jì)算 后,在退出并行區(qū)域時(shí),需要將它的值賦給同名的共享變量,前面的private和firstprivate子句在退出并行區(qū)域時(shí)都沒有將私有變量的最后取 值賦給對應(yīng)的共享變量,lastprivate子句就是用來實(shí)現(xiàn)在退出并行區(qū)域時(shí)將私有變量的值賦給共享變量。

舉個(gè)例子如下:

 
 
 
  1. int k = 100; 
  2. #pragma omp parallel for firstprivate(k),lastprivate(k) 
  3.          for ( i=0; i < 4; i++) 
  4.          { 
  5.                    k+=i; 
  6.                    printf("k=%d/n",k); 
  7.          } 
  8.          printf("last k=%d/n", k); 

 上面代碼執(zhí)行后的打印結(jié)果如下:

 
 
 
  1. k=100 
  2. k=101 
  3. k=103 
  4. k=102 
  5. last k=103 

從打印結(jié)果可以看出,退出for循環(huán)的并行區(qū)域后,共享變量k的值變成了103,而不是保持原來的100不變。

由于在并行區(qū)域內(nèi)是多個(gè)線程并行執(zhí)行的, 最后到底是將那個(gè)線程的最終計(jì)算結(jié)果賦給了對應(yīng)的共享變量呢?OpenMP規(guī)范中指出,如果是循環(huán)迭代,那么是將最后一次循環(huán)迭代中的值賦給對應(yīng)的共享變 量;如果是section構(gòu)造,那么是最后一個(gè)section語句中的值賦給對應(yīng)的共享變量。注意這里說的最后一個(gè)section是指程序語法上的最后一 個(gè),而不是實(shí)際運(yùn)行時(shí)的最后一個(gè)運(yùn)行完的。

如果是類(class)類型的變量使用在 lastprivate參數(shù)中,那么使用時(shí)有些限制,需要一個(gè)可訪問的,明確的缺省構(gòu)造函數(shù),除非變量也被使用作為firstprivate子句的參數(shù); 還需要一個(gè)拷貝賦值操作符,并且這個(gè)拷貝賦值操作符對于不同對象的操作順序是未指定的,依賴于編譯器的定義。

#p#

10.1.4 threadprivate子句

threadprivate子句用來指定全局的對象被各個(gè)線程各自復(fù)制了一個(gè)私有的拷貝,即各個(gè)線程具有各自私有的全局對象。

用法如下:

 
 
 
  1. #pragma omp threadprivate(list) new-line 

下面用threadprivate命令來實(shí)現(xiàn)一個(gè)各個(gè)線程私有的計(jì)數(shù)器,各個(gè)線程使用同一個(gè)函數(shù)來實(shí)現(xiàn)自己的計(jì)數(shù)。計(jì)數(shù)器代碼如下:

 
 
 
  1. int counter = 0; 
  2. #pragma omp threadprivate(counter) 
  3. int increment_counter() 
  4.          counter++; 
  5.          return(counter); 

如果對于靜態(tài)變量也同樣可以使用threadprivate聲明成線程私有的,上面的counter變量如改成用static類型來實(shí)現(xiàn)時(shí),代碼如下:

 
 
 
  1. int increment_counter2() 
  2. static int counter = 0; 
  3. #pragma omp threadprivate(counter) 
  4.          counter++; 
  5.          return(counter); 

threadprivate和private的區(qū)別在于threadprivate聲明的變量通常是全局范圍內(nèi)有效的,而private聲明的變量只在它所屬的并行構(gòu)造中有效。

threadprivate的對應(yīng)只能用于copyin,copyprivate,schedule,num_threads和if子句中,不能用于任何其他子句中。

用作threadprivate的變量的地址不能是常數(shù)。

對于C++的類(class)類型變量,用作threadprivate的參數(shù)時(shí)有些限制,當(dāng)定義時(shí)帶有外部初始化時(shí),必須具有明確的拷貝構(gòu)造函數(shù)。

對于windows系統(tǒng),threadprivate不能用于動態(tài)裝載(使用LoadLibrary裝載)的DLL中,可以用于靜態(tài)裝載的DLL中,關(guān)于windows系統(tǒng)中的更多限制,請參閱MSDN中有關(guān)threadprivate子句的幫助材料。

有關(guān)threadprivate命令的更多限制方面的信息,詳情請參閱OpenMP2.5規(guī)范。

10.1.5 shared子句

shared子句用來聲明一個(gè)或多個(gè)變量是共享變量。

用法如下:

shared(list)

需要注意的是,在并行區(qū)域內(nèi)使用共享變量時(shí),如果存在寫操作,必須對共享變量加以保護(hù),否則不要輕易使用共享變量,盡量將共享變量的訪問轉(zhuǎn)化為私有變量的訪問。

循環(huán)迭代變量在循環(huán)構(gòu)造區(qū)域里是私有的。聲明在循環(huán)構(gòu)造區(qū)域內(nèi)的自動變量都是私有的。

10.1.6 default子句

default子句用來允許用戶控制并行區(qū)域中變量的共享屬性。

用法如下:

default(shared | none)

使用shared時(shí),缺省情況下,傳入并行區(qū)域內(nèi)的同名變量被當(dāng)作共享變量來處理,不會產(chǎn)生線程私有副本,除非使用private等子句來指定某些變量為私有的才會產(chǎn)生副本。 如果使用none作為參數(shù),那么線程中用到的變量必須顯示指定是共享的還是私有的,除了那些由明確定義的除外。

10.1.7 reduction子句

reduction子句主要用來對一個(gè)或多個(gè)參數(shù)條目指定一個(gè)操作符,每個(gè)線程將創(chuàng)建參數(shù)條目的一個(gè)私有拷貝,在區(qū)域的結(jié)束處,將用私有拷貝的值通過指定的運(yùn)行符運(yùn)算,原始的參數(shù)條目被運(yùn)算結(jié)果的值更新。

reduction子句用法如下:

reduction(operator:list)

下表列出了可以用于reduction子句的一些操作符以及對應(yīng)私有拷貝變量缺省的初始值,私有拷貝變量的實(shí)際初始值依賴于redtucion變量的數(shù)據(jù)類型。

表10-4-1:reduction操作中各種操作符號對應(yīng)拷貝變量的缺省初始值

Operator

Initialization value
+ 0
* 1
- 0
& ~0
| 0
^ 0
&& 1
|| 0

 例如一個(gè)整數(shù)求和的程序如下:

 
 
 
  1. int i, sum = 100; 
  2.   
  3. #pragma omp parallel for reduction(+: sum) 
  4. for ( i = 0; i < 1000; i++ ) 
  5.  sum += i; 
  6.   
  7. printf( "sum = %ld/n", sum);

 注意,如果在并行區(qū)域內(nèi)不加鎖保護(hù)就直接對共享變量進(jìn)行寫操作,存在數(shù)據(jù)競爭問題,會導(dǎo)致不可預(yù)測的異常結(jié)果。共享數(shù)據(jù)作為private、firstprivate、lastprivate、threadprivate、reduction子句的參數(shù)進(jìn)入并行區(qū)域后,就變成線程私有了,不需要加鎖保護(hù)了。

#p#

10.1.8copyin子句

copyin子句用來將主線程中threadprivate變量的值拷貝到執(zhí)行并行區(qū)域的各個(gè)線程的threadprivate變量中,便于線程可以訪問主線程中的變量值,

用法如下:

 
 
 
  1. copyin(list) 

 copyin中的參數(shù)必須被聲明成threadprivate的,對于類類型的變量,必須帶有明確的拷貝賦值操作符。

對于前面threadprivate中講過的計(jì)數(shù)器函數(shù),如果多個(gè)線程使用時(shí),各個(gè)線程都需要對全局變量counter的副本進(jìn)行初始化,可以使用copyin子句來實(shí)現(xiàn),示例代碼如下:

 
 
 
  1. int main(int argc, char* argv[]) 
  2.          int iterator; 
  3. #pragma omp parallel sections copyin(counter) 
  4.          { 
  5. #pragma omp section 
  6.                    { 
  7.                             int count1; 
  8.                             for ( iterator = 0; iterator < 100; iterator++ ) 
  9.                             { 
  10.                                      count1 = increment_counter(); 
  11.                             } 
  12.                             printf("count1 = %ld/n", count1); 
  13.                    } 
  14. #pragma omp section 
  15.                    { 
  16.                             int count2; 
  17.                             for ( iterator = 0; iterator < 200; iterator++ ) 
  18.                             { 
  19.                                      count2 = increment_counter(); 
  20.                             } 
  21.                             printf("count2 = %ld/n", count2); 
  22.                    } 
  23.          } 
  24.          printf("counter = %ld/n", counter); 

打印結(jié)果如下:

count1 = 100

count2 = 200

counter = 0

10.1.9 copyprivate子句

copyprivate子句提供了一種機(jī)制用一個(gè)私有變量將一個(gè)值從一個(gè)線程廣播到執(zhí)行同一并行區(qū)域的其他線程。

用法如下:

copyprivate(list)

copyprivate子句可以關(guān)聯(lián)single構(gòu)造,在single構(gòu)造的barrier到達(dá)之前就完成了廣播工作。copyprivate可以對private和threadprivate子句中的變量進(jìn)行操作,但是當(dāng)使用single構(gòu)造時(shí),copyprivate的變量不能用于private和firstprivate子句中。

下面便是一個(gè)使用copyprivate的代碼例子:

 
 
 
  1. int counter = 0; 
  2. #pragma omp threadprivate(counter) 
  3. int increment_counter() 
  4.          counter++; 
  5.          return(counter); 
  6. #pragma omp parallel 
  7.          { 
  8.                    int    count; 
  9. #pragma omp single copyprivate(counter) 
  10.                    { 
  11.                             counter = 50; 
  12.                    } 
  13.                    count = increment_counter(); 
  14.                    printf("ThreadId: %ld, count = %ld/n", omp_get_thread_num(), count); 

打印結(jié)果為:

ThreadId: 2, count = 51

ThreadId: 0, count = 51

ThreadId: 3, count = 51

ThreadId: 1, count = 51

如果沒有使用copyprivate子句,那么打印結(jié)果為:

ThreadId: 2, count = 1

ThreadId: 1, count = 1

ThreadId: 0, count = 51

ThreadId: 3, count = 1

從打印結(jié)果可以看出,使用copyprivate子句后,single構(gòu)造內(nèi)給counter賦的值被廣播到了其他線程里,但沒有使用copyprivate子句時(shí),只有一個(gè)線程獲得了single構(gòu)造內(nèi)的賦值,其他線程沒有獲取single構(gòu)造內(nèi)的賦值。

原文鏈接:http://blog.csdn.net/drzhouweiming/article/details/2033276


本文標(biāo)題:OpenMP中的數(shù)據(jù)處理子句
文章出自:http://www.dlmjj.cn/article/djcgjhc.html