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

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 閱讀(617) 評論(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>
            国产精品v欧美精品v日本精品动漫| 一区免费观看| 亚洲一区二区三区午夜| 亚洲乱码国产乱码精品精天堂 | 亚洲精品一二三| 国产一区二区三区四区在线观看| 国产欧美日韩综合一区在线观看 | 欧美激情欧美激情在线五月| 麻豆精品网站| 亚洲高清毛片| 欧美高清在线视频观看不卡| 欧美成人免费在线| 亚洲人精品午夜| 一区二区精品国产| 亚洲欧美国产毛片在线| 久久久久在线观看| 欧美gay视频激情| 欧美日韩在线大尺度| 国产精品伊人日日| 一区二区三区在线观看欧美| 一区二区电影免费在线观看| 久久国产88| 美女国产精品| 在线综合欧美| 久久米奇亚洲| 欧美少妇一区| 亚洲国产日韩精品| 亚洲欧美日韩精品一区二区| 免费在线欧美视频| 夜夜嗨av一区二区三区中文字幕 | 久久在线播放| 欧美视频导航| 一区二区在线免费观看| 99国产欧美久久久精品| 欧美一区日韩一区| 欧美福利一区| 亚洲免费在线视频| 国产欧美日韩伦理| 国产精品久久久久77777| 国内精品久久久| 中文精品视频一区二区在线观看| 亚洲欧美韩国| 亚洲国产高清在线| 欧美在线一区二区三区| 欧美日韩中字| 亚洲精品免费看| 久久亚洲欧美| 欧美与黑人午夜性猛交久久久| 欧美视频在线一区| 亚洲人成亚洲人成在线观看| 久久深夜福利免费观看| 亚洲小说欧美另类婷婷| 欧美日韩视频第一区| 亚洲电影免费观看高清完整版| 欧美一区1区三区3区公司| 亚洲美女在线一区| 欧美国产在线观看| 亚洲日本黄色| 亚洲国产精品999| 欧美日韩三级视频| 91久久久国产精品| 久久亚洲风情| 久久黄色级2电影| 国产日韩1区| 欧美一区二区三区男人的天堂| 亚洲精品久久久久久久久久久| 久久一区欧美| …久久精品99久久香蕉国产| 久久久久久尹人网香蕉| 久久国产精品高清| 尤物网精品视频| 久久另类ts人妖一区二区| 欧美在线影院| 伊人成人在线视频| 欧美韩国在线| 欧美区国产区| 亚洲亚洲精品三区日韩精品在线视频| 99视频有精品| 国产精品综合色区在线观看| 欧美丝袜第一区| 欧美亚洲尤物久久| 欧美一区二区三区四区在线观看| 国产一区二区在线观看免费| 免费观看国产成人| 欧美人与性动交α欧美精品济南到| 99v久久综合狠狠综合久久| av72成人在线| 国产亚洲欧洲| 亚洲国产二区| 国产精品久久久亚洲一区| 久久久噜噜噜久噜久久| 欧美成人一区二区三区| 亚洲一区二区三区在线视频| 小黄鸭精品密入口导航| 在线成人av.com| av成人福利| 樱花yy私人影院亚洲| 亚洲自拍三区| 免费看成人av| 国产精品v日韩精品| 久久精品一区二区| 欧美精品二区三区四区免费看视频| 一区二区国产在线观看| 午夜精品网站| 夜夜精品视频| 久久久九九九九| 亚洲伊人网站| 久久噜噜亚洲综合| 亚洲一区二区三区精品在线观看| 久久精品国产亚洲一区二区| 一本不卡影院| 久久久久久网| 亚洲影院高清在线| 久久色在线观看| 欧美在线亚洲| 国产精品精品视频| 亚洲国产高清在线| 国产专区欧美精品| 亚洲精品国产欧美| 精品粉嫩aⅴ一区二区三区四区| 亚洲视频免费看| 亚洲日韩第九十九页| 欧美一二三区精品| 亚洲女与黑人做爰| 欧美激情综合在线| 久久免费精品视频| 欧美日韩亚洲综合| 最近看过的日韩成人| 亚洲成色精品| 亚洲欧美日韩另类| 亚洲在线视频观看| 国产精品99免视看9| 亚洲精品国久久99热| 日韩视频久久| 欧美人成网站| 亚洲黄色影院| 亚洲激情成人网| 久久这里只有精品视频首页| 久久久噜久噜久久综合| 国产日韩一区二区三区在线播放 | 另类成人小视频在线| 久久久人成影片一区二区三区观看| 国产精品女同互慰在线看| 日韩午夜av电影| 亚洲午夜一区二区三区| 国产精品videosex极品| 99精品国产在热久久下载| 亚洲精品一区二区网址| 欧美成在线观看| 亚洲电影成人| 亚洲三级影院| 欧美激情欧美狂野欧美精品| 亚洲精品综合精品自拍| 亚洲一区制服诱惑| 国产欧美丝祙| 久久国产精品久久久久久久久久| 久久久久国内| 亚洲国产精品专区久久| 欧美精品v国产精品v日韩精品| 亚洲精品免费一二三区| 亚洲作爱视频| 一区二区三区三区在线| 国产亚洲午夜| 欧美伊人影院| 欧美国产一区视频在线观看| 亚洲精品美女久久久久| 欧美日韩美女一区二区| 亚洲一区三区在线观看| 欧美在线观看一区二区三区| 一色屋精品视频在线看| 欧美福利网址| 亚洲综合不卡| 欧美成人一区二免费视频软件| 亚洲区一区二区三区| 国产精品成人免费| 欧美一区午夜精品| 亚洲国产一区二区三区青草影视 | 日韩一二三区视频| 亚洲欧美日本精品| 极品中文字幕一区| 欧美精品一区二区三区蜜桃| 亚洲一区二区三区四区中文| 欧美sm极限捆绑bd| 亚洲午夜精品网| 亚洲丰满在线| 国产美女精品| 欧美精品一区二区三区蜜桃 | 欧美一区二区三区四区视频| 黄色欧美日韩| 国产精品久久久久久久浪潮网站| 久久九九国产| 亚洲自拍偷拍色片视频| 欧美黄色一级视频| 欧美综合激情网| 亚洲综合日韩在线| 99精品国产在热久久婷婷| 影音先锋久久资源网| 国产区日韩欧美| 国产精品视频免费一区| 欧美日韩中文字幕精品|