青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++ Coder

HCP高性能計算架構,實現,編譯器指令優化,算法優化, LLVM CLANG OpenCL CUDA OpenACC C++AMP OpenMP MPI

C++博客 首頁 新隨筆 聯系 聚合 管理
  98 Posts :: 0 Stories :: 0 Comments :: 0 Trackbacks
http://blog.csdn.net/bendanban/article/details/6303100

   openMP并不是只能對循環來并行的,循環并行化單獨拿出來說是因為它在科學計算中非常有用,比如向量、矩陣的計算。所以我單獨拿出這一部分給大家講講。這里主要講解的是for循環。

編譯指導語句:

    一般格式:

    #pragma omp parallel for [clause[clause…]]

    for(index = first; qualification; index_expr)

    {…}

    第一句中[]的部分是可選的,由自己的程序并行特點而定。大家先不要把精力放到這里面。后面的文章中會繼續講解的。

并行化for的編寫規則

    1、index的值必須是整數,一個簡單的for形式:for(int i = start; i < end; i++){…} 。

    2、start和end可以是任意的數值表達式,但是它在并行化的執行過程中值不能改變,也就是說在for并行化執行之前,編譯器必須事先知道你的程序執行多少次,因為編譯器要把這些計算分配到不同的線程中執行。

    3、循環語句只能是單入口但出口的。這里只要你避免使用跳轉語句就行了。具體說就是不能使用goto、break、return。但是可以使用continue,因為它并不會減少循環次數。另外exit語句也是可以用的,因為它的能力太大,他一來,程序就結束了。

例子講解

例1、for循環并行:

#include 
#include 
"omp.h" 
int main(int argc, char* argv[]) 

    
int i; 
    #pragma omp parallel 
for 
    
for (i = 0; i < 12; i++
    
{        printf("i = %d  %d/n", i, omp_get_thread_num());    } 
    
return 0
}

 

例1的執行結果如圖1所示:

image

圖1、例1的執行結果

從結果中可以看出 i 屬于{0,1,2}時由0號線程執行,i 屬于{3,4,5}時由1號線程執行,i 屬于{6,7,8}時由2號線程執行,i 屬于{9,10,11}時由3號線程執行。omp_get_thread_num()這個函數通過執行結果大家也知道了,他返回每個線程的編號。

并行編譯子句

    openMP中有多種并行化子句,這些子句都是為控制循環并行化編譯而設定的,這里我們主要關注數據作用域子句,這里的數據作用域是指各個線程是否對某一變量有權訪問。shared子句用來標記變量在各個線程之間是共享的,private子句標記變量在各個線程之間是私有的,實際上它會在在每個線程中保存一個副本。默認情況下,并行執行的變量是共享的。至于其它編譯子句將在后面的文章中介紹。

用實例講解數據作用域子句

實際上我很難想到一個綜合的例子來講解這種子句的限制異同,所以我寫了幾個例子。

例2、private

#include
#include "omp.h"
int main(int argc, char* argv[])
{
    float x = 4.3f;
    int i;
    #pragma omp parallel for private(x)
    for (i = 0; i < 12; i++)
    {
        x = 0;
        printf("parallel x = %.1f, thread nummber:%d/n", x, omp_get_thread_num());
    }
    printf("/nserial   x = %.1f, thread nummber:%d/n", x, omp_get_thread_num());
    return 0;
}

image

圖2、例2執行結果

例3 firstprivate(var):指定var在每個線程中都有一個副本,并且var的初始值在并行執行開始之前定義,每個并行線程的var的副本初值就是串行時定義的初始值。程序結束后串行程序中的var值并不會改變。

#include 
#include 
"omp.h" 
int main(int argc, char* argv[]) 

    
float x = 4.3f
    
int i; 
    #pragma omp parallel 
for firstprivate(x) 
    
for (i = 0; i < 12; i++
    

        x 
+= 1.0f
        printf(
"parallel x = %.1f, thread nummber:%d/n", x, omp_get_thread_num());        
    }
 
    printf(
"/nserial   x = %.1f, thread nummber:%d/n", x, omp_get_thread_num()); 
    
return 0
}

 

 

image

圖3、例3的執行結果

例4 lastprivate(var):指定最后多線程執行完后原串行循環最后一次var的值帶到主線程(串行部分)

#include 
#include 
"omp.h" 
int main(int argc, char* argv[]) 

    
float x = 4.3f
    
int i; 
    #pragma omp parallel 
for lastprivate(x) 
    
for (i = 0; i < 12; i++
    
{        
        x 
= 0.0f
        printf(
"parallel x = %.1f, thread nummber:%d/n", x, omp_get_thread_num());        
    }
 
    printf(
"/nserial   x = %.1f, thread nummber:%d/n", x, omp_get_thread_num()); 
    
return 0
}

image

圖4、例4的執行結果

例5 firstprivate與lastprivate聯用,很奇怪openMP很多情況下是不允許某個變量被指定兩次規則的,他倆卻可以,呵呵,而且配合效果還不錯。

#include 
#include 
"omp.h" 
int main(int argc, char* argv[]) 

    
float x = 4.3f
    
int i; 
    #pragma omp parallel 
for firstprivate(x) lastprivate(x) 
    
for (i = 0; i < 12; i++
    
{        
        x 
+= (float)omp_get_thread_num(); 
        printf(
"parallel x = %.1f, thread nummber:%d/n", x, omp_get_thread_num());        
    }
 
    printf(
"/nserial   x = %.1f, thread nummber:%d/n", x, omp_get_thread_num()); 
    
return 0
}

image

圖5、例5的執行結果

    從上面的例2、3的程序中可以看出例2中每個線程中x都是私有的,它屬于每個線程,在主線程的定義并不能帶入到各個線程中,使用firstprivate后,x在主線程的初始值可以帶到各個線程中,在圖3可以看出每個線程x的輸出結果實際是相同的,但是在并行執行結束后,主線程中的x值仍然為4.3。從例4的執行結果可以看出最后x的值帶出到了主線程中,這個x值到底是哪個線程中的哪?答案是最后一句x賦值后的值,哪個線程執行完的最晚就是哪個x的值。例5顯示firstprivate與lastprivate聯合使用的執行結果。

例6 reduction規約操作,

    執行reduction的變量要特別注意,以reduction(+:sum)為例。

    第一種情況:sum為局部變量。這是你必須為sum在串行程序中賦初值,sum 被設置為每個線程私有,先各自執行完算出各自的sum值,最后主線程會將 《線程數+1》個sum變量規約,比如你num_thread(4),在開始并行執行之前你對規約變量賦初值為10,并行時假設每個線程算的的sum值為1,那么最終sum帶到串行程序中的變量值為14(串行的10+四個線程的1)。

    第二種情況:sum為全局變量。這是你不必為sum賦初始值,因為此時默認串行的sum值為0,進入每個線程的sum值也是0,規約時仍然是將《線程數+1》個sum值相加,因為你并沒有對全局的sum賦初值,所以最后規約的結果看著像是只有各線程的sum參加了規約操作。其實當你將全局的sum賦初值時,你會發現最后規約的sum值又多加了全局變量sum的串行程序結果。

    重要提醒:不管你怎樣設計sum的串行聲明形式,只要他在被定義為規約變量,每次進入并行線程的sum值都是0;

    也許你想把每個并行線程的sum值初始化成一個非0的值,然后再各自線程中在使用,那么我可以告訴你,別想了(至少我沒有做到)。因為我規約sum值,如果這個規約有意義你的每個線程應該是各自獨立未回各自的sum的,那么這個初始值使用0就已經非常好了,因為各自的sum計算如果結果一樣,你為何不直接用一句乘法哪(線程數*一個線程計算的sum值)。

#include 
#include 
"omp.h" 
int main(int argc, char* argv[]) 

    
float x = 0.0f
    
int i; 
    
float sum = 0.0f
#pragma omp parallel 
for private(x) reduction(+:sum) 
    
for (i = 0; i < 12; i++
    
{        
        x 
= (float)omp_get_thread_num(); 
        sum 
+= x; 
        printf(
"parallel sum = %.1f, thread nummber:%d/n", sum, omp_get_thread_num());        
    }
 
    printf(
"/nserial   sum = %.1f, thread nummber:%d/n", sum, omp_get_thread_num()); 
    
return 0
}

image

圖6、例6執行結果

    在例6中我使用了reduction(+:sum),這表示每個線程對sum這個共享變量執行加操作時其它任何線程不能對它進行加操作,實際上我們這樣理解是有偏差的,真正的機理在執行結果中不難看出,實際每個線程都拷貝了一個sum的副本,先在自己執行時加完sum,等所有線程都執行結束后,主線程再將每個線程的sum副本的值加起來返回給主線程中sum。

小結

    本節主要講述了for語句的并行化。現在為止大家應該可以熟練使用for并行化了。文章中可能還有些不全面的地方,熱切期望各位讀者能給出批評和指正,期待中……


posted on 2012-10-21 11:54 jackdong 閱讀(624) 評論(0)  編輯 收藏 引用 所屬分類: OPenMP
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美成人免费播放| 午夜亚洲性色视频| 亚洲国产欧美日韩| 欧美一区二区久久久| 欧美一区二区视频观看视频| 亚洲娇小video精品| 亚洲激情在线观看| 亚洲第一级黄色片| 国产综合激情| 欧美日韩一二三四五区| 欧美成人中文| 久久精品成人一区二区三区蜜臀| 亚洲经典三级| 亚洲午夜伦理| 亚洲精品欧美一区二区三区| 国产精品久久综合| 久久激情五月丁香伊人| 在线视频亚洲欧美| 亚洲激情视频网| 9久re热视频在线精品| 亚洲经典三级| 日韩性生活视频| 午夜精品在线观看| 老鸭窝91久久精品色噜噜导演| 欧美一区二区视频97| 国产欧美一区二区精品性| 欧美黄色影院| 免费成人av资源网| 麻豆精品在线视频| 久久激情五月丁香伊人| 欧美在线精品一区| 宅男噜噜噜66一区二区| 99热免费精品| 国产精品欧美日韩一区二区| 国产一区二区在线免费观看 | 亚洲人成网站777色婷婷| 另类激情亚洲| 欧美一二区视频| 亚洲国产一区二区三区高清| 亚洲高清在线| 最新69国产成人精品视频免费| 国产视频一区在线观看| 亚洲品质自拍| 亚洲国产精品成人精品| 一区二区三区精品在线| 亚洲视频在线视频| 欧美色综合天天久久综合精品| 国产精品剧情在线亚洲| 国产一区二区三区在线观看精品| 亚洲第一黄色| 亚洲综合导航| 亚洲欧美在线磁力| 欧美精品手机在线| 国产精品乱人伦中文| 亚洲精品日韩精品| 亚洲欧美日韩视频一区| 久久久久欧美| 亚洲老板91色精品久久| 久久久99久久精品女同性| 欧美激情亚洲综合一区| 91久久国产综合久久91精品网站| 亚洲欧美综合国产精品一区| 91久久亚洲| 老司机凹凸av亚洲导航| 欧美一区二区视频在线| 久久婷婷综合激情| 亚欧成人在线| 国产欧美在线看| 香蕉乱码成人久久天堂爱免费| 日韩视频在线免费| 欧美日韩一区在线| 中文久久精品| 国产精品99久久99久久久二8| 欧美日韩国产综合在线| 一本综合精品| 制服丝袜激情欧洲亚洲| 国产精品激情| 你懂的成人av| 国产精品久久久久久久久| 99热这里只有成人精品国产| 欧美国产视频在线| 欧美福利在线观看| 一区二区三区视频在线播放| 99视频有精品| 国产欧美日韩精品丝袜高跟鞋| 久久精品123| 久久久最新网址| 亚洲精品在线看| 亚洲夜晚福利在线观看| 国产一区二区三区四区老人| 欧美va亚洲va香蕉在线| 欧美韩日一区二区| 午夜精品久久久久久久久| 午夜视频一区在线观看| 亚洲日本va午夜在线电影| 亚洲精选视频在线| 国产欧美一区二区三区久久| 欧美肥婆在线| 欧美性猛交xxxx乱大交退制版| 久久精品99无色码中文字幕 | 亚洲一区二区三区精品动漫| 国产一区二区三区高清播放| 亚洲国产综合91精品麻豆| 国产精品区二区三区日本 | 最新日韩在线视频| 亚洲影视九九影院在线观看| 亚洲国内自拍| 午夜精品久久久久久久男人的天堂 | 在线日韩中文字幕| 亚洲一区二区三区中文字幕| 一区二区在线看| 一区二区三区www| 亚洲国产专区| 欧美一区二区三区四区在线| 在线亚洲精品| 免费久久久一本精品久久区| 欧美一区二区三区四区在线观看地址| 久久亚洲影音av资源网| 亚洲欧美清纯在线制服| 欧美精品国产| 欧美国产精品日韩| 黄色日韩网站| 亚洲欧美在线一区| 一区二区三区免费网站| 免费在线视频一区| 欧美成va人片在线观看| 国产农村妇女毛片精品久久莱园子 | 女人香蕉久久**毛片精品| 国产精品一卡二卡| 一区二区电影免费观看| 亚洲欧洲日产国产综合网| 亚洲精品无人区| 玖玖综合伊人| 免费欧美日韩| 欧美aⅴ一区二区三区视频| 亚洲一区观看| 亚洲免费在线视频| 老司机精品视频网站| 欧美精品激情| 欧美一级视频精品观看| 久久久国产精品亚洲一区| 猛男gaygay欧美视频| 欧美有码在线观看视频| 欧美.www| 欧美国产日韩视频| 精品成人一区二区三区| 欧美四级电影网站| 亚洲欧洲三级| 99精品国产在热久久婷婷| 欧美体内she精视频| 国产精品久久久久久久久久三级 | 美女视频黄免费的久久| 欧美日韩在线播放三区| 国产免费一区二区三区香蕉精| 欧美日韩国产影片| 欧美性猛交99久久久久99按摩| 欧美亚洲一区在线| 欧美顶级少妇做爰| 欧美日本不卡| 六月婷婷一区| 极品少妇一区二区三区| 国产日韩三区| 一区二区三区视频在线看| 美女国内精品自产拍在线播放| 亚洲视频精品在线| 国产视频一区二区三区在线观看| 国产亚洲福利社区一区| 日韩手机在线导航| 亚洲精选视频免费看| 久久午夜精品| 蜜桃av一区二区| 亚洲欧美日韩直播| 久久久久五月天| 国产一区二区三区电影在线观看| 久久国产精品99国产精| 久久久不卡网国产精品一区| 狠狠久久亚洲欧美| 久久网站免费| 日韩一二三区视频| 久久国产精品久久国产精品| 国产一区二区三区电影在线观看| 玖玖玖免费嫩草在线影院一区| 亚洲激情视频在线观看| 午夜精品久久久久久久99樱桃| 樱桃成人精品视频在线播放| 欧美啪啪一区| 久久av红桃一区二区小说| 韩国女主播一区| 欧美性片在线观看| 国产精品久久久久久久电影| 午夜精品一区二区三区在线播放| 玖玖视频精品| 午夜视频在线观看一区二区三区| 亚洲综合视频在线| 亚洲人体影院| 免费日韩一区二区| 亚洲欧美久久| 欧美插天视频在线播放| 日韩视频在线观看免费| 欧美国产日韩一二三区|