openmp并行編程中科院_第1頁
openmp并行編程中科院_第2頁
openmp并行編程中科院_第3頁
openmp并行編程中科院_第4頁
openmp并行編程中科院_第5頁
已閱讀5頁,還剩72頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、OpenMP并行編程中科院計(jì)算機(jī)網(wǎng)絡(luò)信息中心超級計(jì)算中心1OpenMP編程簡介 OPenMP編程制導(dǎo)OpenMP庫函數(shù)OpenMP環(huán)境變量OpenMP計(jì)算實(shí)例2022/8/182并行機(jī)體系結(jié)構(gòu)及通信機(jī)制(回顧) PVP:并行向量機(jī) 共享變量 、單地址空間 、集中共享、UMA SMP:共享存貯并行機(jī),它是由多個處理器通過交叉開關(guān)(Crossbar)或開關(guān)(SWITCH)與內(nèi)存互連。 共享變量 、單地址空間 、集中共享、UMAMPP:分布式存貯并行機(jī),它是由稱為結(jié)點(diǎn)通過消息傳遞網(wǎng)絡(luò)互連而成。 共享變量 、多地址空間、分布非共享、NORMA2022/8/183DSM:分布共享存貯并行機(jī),它是由結(jié)點(diǎn)(

2、一般是SMP系統(tǒng))通過高速消息傳遞網(wǎng)絡(luò)互連而成。存貯系統(tǒng)物理上是分布的,各結(jié)點(diǎn)有自己獨(dú)立的尋址空間,然而在邏輯上存貯系統(tǒng)是共享的。 共享變量 、單地址空間 、分布共享、NUMACluster(Now,Cow)群集系統(tǒng):將單個處理器,用Ethernet,Myrinet,Quadrics,Infiniband,Switch連結(jié)起來形成群集系統(tǒng)。 將SMP結(jié)點(diǎn)用高速網(wǎng)連結(jié)起來。 將DSM用高速網(wǎng)連結(jié)起來。 共享變量 、多地址空間、分布非共享、NORMA2022/8/184OpenMP編程簡介2022/8/185OpenMP簡介 OpenMP是共享存儲體系結(jié)構(gòu)上的 一個并行編程模型。適合于SMP共享內(nèi)

3、存多處理系統(tǒng)和多核處理器體系結(jié)構(gòu)。起源于ANSI X3H5標(biāo)準(zhǔn) 簡單、移植性好和可擴(kuò)展性等特點(diǎn) 提供了支持Fortran、C/C+的API和規(guī)范由一組編譯制導(dǎo)、運(yùn)行時庫函數(shù)(Run-Time routines) 和環(huán)境變量組成。 工業(yè)標(biāo)準(zhǔn)DEC、Intel、IBM、HP、Sun、SGI等公司支持包括Linux、UNIX和NT等多種操作系統(tǒng)平臺 2022/8/186OpenMP并行編程模式OpenMP是基于線程的并行編程模型。OpenMP采用Fork-Join并行執(zhí)行方式:OpenMP程序開始于一個單獨(dú)的主線程(Master Thread),然后主線程一直串行執(zhí)行,直到遇見第一個并行域(Para

4、llel Region),然后開始并行執(zhí)行并行域。其過程如下: Fork:主線程創(chuàng)建一個并行線程隊(duì)列,然后,并行域中的代碼在不同的線程上并行執(zhí)行; Join:當(dāng)并行域執(zhí)行完之后,它們或被同步或被中斷,最后只有主線程在執(zhí)行。2022/8/187OpenMP程序并行框架FORKJIONFORKJIONMasterthread并行域并行域串行部分串行部分串行部分2022/8/188簡單的”Hello, world”O(jiān)penMP并性程序 /* 用OpenMP/C編寫Hello World代碼段 */ #include int main(int argc, char *argv) int nthread

5、s,tid;int nprocs;char buf32; /* Fork a team of threads */ #pragma omp parallel private(nthreads,tid) /* Obtain and print thread id */ tid = omp_get_thread_num(); printf(Hello, world from OpenMP thread %dn, tid); /*Only master thread does this */ if (tid = 0) nthreads = omp_get_num_threads(); printf(

6、 Number of threads %dn,nthreads); return 0; 2022/8/189 編譯執(zhí)行: efc -openmp o HelloWorld HelloWorld.c ./HelloWorld 運(yùn)行結(jié)果: Hello World from OpenMP thread 2 Hello World from OpenMP thread 0 Number of threads 4 Hello World from OpenMP thread 3 Hello World from OpenMP thread 12022/8/1810OpenMP程序結(jié)構(gòu)基于Fortran語

7、言的OpenMP程序結(jié)構(gòu) PROGRAM PROG_NAME INTEGER VAR1, VAR2 ,VAR3 . !$OMP PARALLEL PRIVATE(VAR1, VAR2) SHARED(VAR3) . !$OMP END PARALLEL END2022/8/1811基于C/C+語言的OpenMP程序結(jié)構(gòu) #include main() int var1, var2, var3; . #pragma omp parallel private(var1, var2) shared(var 3) . 2022/8/1812OpenMP編譯制導(dǎo)2022/8/1813OpenMP的并行化

8、是通過使用嵌入到C/C+或Fortran源代碼中的編譯制導(dǎo)語句來實(shí)現(xiàn)。編譯制導(dǎo)是對程序設(shè)計(jì)語言的擴(kuò)展。支持并行區(qū)域、工作共享、同步等。支持?jǐn)?shù)據(jù)的共享和私有化。通過對串行程序添加制導(dǎo)語句實(shí)現(xiàn)并行化2022/8/1814制導(dǎo)語句格式 編譯制導(dǎo)語句由下列幾部分組成: 制導(dǎo)標(biāo)識符 ( !$OMP 、 #pragma omp ) 制導(dǎo)名稱(parallel,DO/for,section等) 子句(privated ,shared,reduction,copyin等) 格式:制導(dǎo)標(biāo)識符 制導(dǎo)名稱 Cluase,2022/8/1815編譯制導(dǎo)標(biāo)識(sentinels)制導(dǎo)是特殊的、僅用于特定編譯器的源代碼。

9、制導(dǎo)由一個位于行首的標(biāo)識加以區(qū)分。OpenMP 制導(dǎo)標(biāo)識:Fortran: !$OMP (or C$OMP or *$OMP)C/C+: #pragma omp2022/8/1816并行域制導(dǎo)一個并行域就是一個能被多個線程并行執(zhí)行的程序段Fortran: !$OMP PARALLEL clauses BLOCK !$OMP END PARALLELC/C+: #pragma omp parallel clauses BLOCK 2022/8/1817說明在并行域結(jié)尾有一個隱式同步(barrier)。子句(clause)用來說明并行域的附加信息。在Fortran語言中,子句間用逗號或空格分隔;

10、C/C+子句間用空格分開。2022/8/1818并行域結(jié)構(gòu):例圖ThreadsThreadsMaster threadMaster threadbarrierbarrierMaster thread2022/8/1819shared 和privated子句并行域內(nèi)的變量,可以通過子句說明為公有或私有;在編寫多線程程序時,確定哪些數(shù)據(jù)的公有或私有非常重要:影響程序的性能和正確性Fortran: SHARED(list) PRIVATE(list) DEFAULT(SHARED|PRIVATE|NONE)C/C+: shared(list) private(list) default(shared

11、|private|none)2022/8/1820例:每個線程初始共享數(shù)組的一列!$OMP PARALLEL DEFAULT(NONE), PRIVATE(I, MYID), !$OMP & SHARED(a, n) myid=omp_get_thread_num()+1 do i=1, n a(i, myid)=1.0 end do!$OMP END PARALLEL說明:如何決定哪些變量是共享哪些是私有?通常循環(huán)變量、臨時變量、寫變量一般是私有的;數(shù)組變量、僅用于讀的變量通常是共享的。默認(rèn)時為公有。i02312022/8/1821并行域結(jié)構(gòu):reduction子句歸約用來從相關(guān)的操作(+,

12、*,max或min等)中產(chǎn)生一個單一值;OpenMP提供了reduction子句。Fortran:REDUCTION(op:list)C/C+: reduction(op:list)例子:將一組數(shù)值歸約求和 sum=0; $OMP PARALLEL REDUCTION(+: sum), PRIVATE(I, MYID) myid=omp_get_thread_num()+1 do i= 1, n sum=sum+a(i, myid) end do $OMP END PARALLEL說明:在reduction子句中,編譯器為每個線程創(chuàng)建變量sum的私有副本。當(dāng)循環(huán)完成后,將這些值加在一起并把結(jié)果

13、放到原始的變量sum中;Reduction中的op操作必須滿足算術(shù)結(jié)合律和交換律。2022/8/1822計(jì)算Pi值/* Seriel Code */static long num_steps = 100000; double step; void main () int i; double x, pi, sum = 0.0, start_time,end_time; step = 1.0/(double) num_steps; start_time=clock(); for (i=1;i= num_steps; i+) x = (i-0.5)*step; sum = sum + 4.0/(1.

14、0+x*x); pi = step * sum; end_time=clock(); printf(“Pi=%fn Running time n”, pi, end_time-start_time); 2022/8/1823并行域并行(SPMD并行模式)include static long num_steps = 100000; double step; #define NUM_THREADS 4 void main () int i ; double pi, sumNUM_THREADS , start_time, end_time ; step = 1.0/(double) num_st

15、eps; omp_set_num_threads(NUM_THREADS) start_time=omp_get_wtime(); #pragma omp parallel int id; double x; id = omp_get_thraead_num(); for (i=id, sumid=0.0;i num_steps; i=i+NUM_THREADS) x = (i+0.5)*step; sumid += 4.0/(1.0+x*x); for(i=0, pi=0.0;iNUM_THREADS;i+)pi += sumi * step; end_time=omp_get_wtime(

16、); printf(“Pi=%fn Running time n”, pi, end_time-start_time); 2022/8/1824任務(wù)劃分并行制導(dǎo) 制導(dǎo)可以出現(xiàn)在并行域內(nèi)部,并表明任務(wù)如何在多個線程間分配,OpenMP任務(wù)劃分制導(dǎo)包括: 并行DO/for循環(huán)制導(dǎo)并行SECTIONS制導(dǎo)SINGLE和MASTER制導(dǎo)其它制導(dǎo)2022/8/1825并行DO/for循環(huán)制導(dǎo)并行DO/for循環(huán)制導(dǎo)用來將循環(huán)劃分成多個塊,并分配給各線程并行執(zhí)行。Fortran:!$OMP DOclauses DO 循環(huán)!$OMP END DOC/C+:#pragma omp for clauses fo

17、r 循環(huán)說明: 并行DO/for循環(huán)有時需要PRIVATE和FIRSTPRIVARE子句; 循環(huán)變量是私有的。 2022/8/1826可以將并行域和DO/for制導(dǎo)結(jié)合成單一的簡單形式Fortran: !$OMP PARALLEL clauses !$OMP DOclauses 循環(huán)體 !$OMP END DO !$OMP END PARALLEL合并后形式: !$OMP PARALLEL DOclauses 循環(huán)體 !$OMP END PARALLEL DO同樣地,C/C+:合并后形式 #pragma omp parallel for clauses 循環(huán)體 2022/8/1827并行DO/

18、for循環(huán)制導(dǎo):調(diào)度子句SCHEDULE該子句給出迭代循環(huán)劃分后的塊大小和線程執(zhí)行的塊范圍Fortran: SCHEDULE(kind, chunksize)C/C+: schedule (kind, chunksize)其中:kind為STATIC, DYNAMIC或RUNTIME chunksize是一個整數(shù)表達(dá)式例如:!$ OMP DO SCHEDULE (DYNAMIC,4) 循環(huán)體!$ OMP DO2022/8/1828子句說明schedule (STATIC , chunksize) : 省略chunksize,迭代空間被劃分成(近似)相同大小 的區(qū)域,每個線程被分配一個 區(qū)域;

19、如果chunksize被指明,迭代空間被劃分為chunksize大小,然后被輪轉(zhuǎn)的分配給各個線程 例如:假如線程數(shù)為4 schudule(static) T0 T1 T2 T3 1 40 schudule(static, 4) T0 T1 T2 T3 T0 T1 T2 T3 T0 T1 1 40 2022/8/1829并行DO/for循環(huán)制導(dǎo):調(diào)度子句SCHEDULEschedule (DYNAMIC , chunksize) :劃分迭代空間為chunksize大小的區(qū)間,然后基于先來先服務(wù)方式分配給各線程;當(dāng)省略chunksize時,其默認(rèn)值為1。schedule (GUIDED , chu

20、nksize) 類似于DYNAMIC調(diào)度,但區(qū)間開始大,然后迭代區(qū)間越來越少,循環(huán)區(qū)間的劃分是基于類似下列公式完成的(不同的編譯系統(tǒng)可能不同): 其中N是線程個數(shù),Sk表示第k塊的大小,Rk是剩余下未被調(diào)度的循環(huán)迭代次數(shù)。chunksize說明最小的區(qū)間大小。當(dāng)省略chunksize時,其默認(rèn)值為1。schedule (RUNTIME)調(diào)度選擇延遲到運(yùn)行時,調(diào)度方式取決于環(huán)境變量OMP_SCHEDULE的值,例如: export OMP_SCHEDULE=DYNAMIC, 4;使用 RUNTIME時,指明chunksize是非法的; 2022/8/1830使用for循環(huán)制導(dǎo)計(jì)算pi值#incl

21、ude #define NUM_THREADS 4static long num_steps = 100000; double step; void main () int i,id; double x, pi, sumNUM_THREADS; step = 1.0/(double) num_steps; omp_set_num_threads(NUM_THREADS) #pragma omp parallel private(x, id) id = omp_get_thread_num(); sumid = 0; #pragma omp for for (i=id;i num_steps;

22、i+) x = (i+0.5)*step; sumid += 4.0/(1.0+x*x); for(i=0, pi=0.0;iNUM_THREADS; i+) pi += sumi * step; 2022/8/1831調(diào)度子句SCHEDULE例圖2022/8/1832數(shù)據(jù)競爭問題下面的循環(huán)無法正確執(zhí)行: #pragma omp parallel for for(k=0;k100;k+) x=arrayk; arrayk=do_work(x); 正確的方式: 直接聲明為私有變量 #pragma omp parallel for private(x) for(k=0;k100;k+) x=arr

23、ayk; arrayk=do_work(x); 在parallel結(jié)構(gòu)中聲明變量,這樣的變量是私有的。#pragma omp parallel forfor(k=0;k100;k+) int x; x=arrayk; arrayk=do_work(x);2022/8/1833SECTIONS制導(dǎo):任務(wù)分配區(qū)任務(wù)分配區(qū)(work-sharing sections)可以使OpenMP編譯器和運(yùn)行時庫將應(yīng)用程序中標(biāo)出的結(jié)構(gòu)化塊(block)分配到并行區(qū)域的一組線程上Fortran: !$OMP SECTIONSclauses !$OMP SECTION block !$OMP SECTION blo

24、ck !$OMP END SECTIONSC/C+: $pragma sectionsclauses $pragma section block $pragma section block . 2022/8/1834說明:各結(jié)構(gòu)化塊在各線程間并行執(zhí)行: 結(jié)構(gòu)化塊的數(shù)量少于線程個數(shù)?; 結(jié)構(gòu)化塊的數(shù)量大于線程個數(shù)?。sections制導(dǎo)可以帶有PRIVATE、 FIRSTPRIVATE和其它子句;每個section必須包含一個結(jié)構(gòu)體。將并行域和SECTIONS制導(dǎo)結(jié)合成單一的簡單形式:Fortran: $OMP PARALLEL SECTIONSclauses . $OMP END PARALL

25、EL SECTIONSC/C+: $pragma parallel sectionsclauses . $pragma end parallel sections2022/8/1835并行SECTIONS制導(dǎo):例句!$OMP PARALLEL !$OMP DO 循環(huán)體 !$OMP END DO !$OMP SECTIONS !$OMP SECTION call init(x) !$OMP SECTION call init(y) !$OMP SECTION call init(z) !$OMP END SECTIONS!$OMP END PARALLEL假如有4個線程迭代塊1迭代塊2迭代塊3迭

26、代塊4 init(x)init(y) init(z) idle 2022/8/1836SINGLE制導(dǎo)SINGLE制導(dǎo):Fortran: !OMP SINGLE clauses block !OMP END SINGLEC/C+:#pragma omp single clauses structure block說明: 結(jié)構(gòu)體代碼僅由一個線程執(zhí)行;并由首先執(zhí)行到該代碼的線程執(zhí)行;其它線程等待直至該結(jié)構(gòu)塊被執(zhí)行完例子#pragma omp parallel setup(x); #pragma omp single input(y); work(x,y); 2022/8/1837SINGLE制導(dǎo):

27、例圖#pragma omp parallel setup(x); #pragma omp single input(y); work(x,y); 2022/8/1838MASTER制導(dǎo)MASTER制導(dǎo)Fortran: !OMP MASTER clauses block !OMP END MASTER C/C+:#pragma omp master clauses structure block說明: 結(jié)構(gòu)體代碼僅由主線程執(zhí)行;其它線程跳過并繼續(xù)執(zhí)行;通常用于I/O;2022/8/1839BARRIER制導(dǎo)BARRIER是OpenMP用于線程同步的一種方法Fortran:!$ OMP BARRI

28、ERC/C+:#pragma omp barrier說明:在所有的線程到達(dá)之前,沒有線程可以提前通過一個barrier;在DO/FOR、SECTIONS和SINGLE制導(dǎo)后,有一個隱式barrier 存在;要么所有線程遇到barrier;要么沒有線程遇到barrier,否則會出現(xiàn)死鎖。2022/8/1840例子! $OMP PARALLEL PRIVATE(i, myid, neighb) myid=omp_get_thread_num() neighb=myid-1 if (myid .eq. 0) neighb=omp_get_num_threads()-1 a(myid)=a(myid)

29、*3.5 ! $ OMP BARRIER b(myid)=a(neighb)+c ! $ OMP END PARALLEL2022/8/1841使用帶reduction子句的for循環(huán)制導(dǎo)#include #define NUM_THREADS 4static long num_steps = 100000; double step; void main () int i,id; double x, pi, sum, start_time, end_time; step = 1.0/(double) num_steps; omp_set_num_threads(NUM_THREADS) ; s

30、tart_time=omp_get_wtime(); #pragma omp parallel private(x, id) id = omp_get_thread_num(); sumid = 0; #pragma omp for private(x) shared(sum) reductuion(+:sum) for (i=id;i num_steps; i+) x = (i+0.5)*step; sum += 4.0/(1.0+x*x); start_time=omp_get_wtime(); pi=sum*step; printf(“Pi=%fn Running time n”,end

31、_time-start_time);2022/8/1842NOWAIT 子句Nowait子句可以除去隱藏在循環(huán)、SECTIONS或并行區(qū)后的同步Fortran:!OMP DO do loop! OMP END DO NOWAITC/C+:#pragma omp for nowait for loop SECTIONS制導(dǎo)和SINGLE制導(dǎo) 有類似形式說明: 使用NOWAIT時要特別小心,有可能導(dǎo)致不可確定的bug;2022/8/1843在有些地方使用NOWAIT可能是好的代碼形式,并且顯式的使用BARRIERS例子:兩個循環(huán)間沒有依賴性!$OMP PARALLEL !$ OMP do do j

32、=1, n . ! $ OMP END DO NOWAIT ! $ OMP do do j=1, n . ! $ OMP END DO NOWAIT!OMP END PARALLEL2022/8/1844保存共享變量:CRITICAL制導(dǎo)CRITICAL(臨界段)可以保護(hù)共享變量的更新,避免數(shù)據(jù)競爭,制導(dǎo)內(nèi)的代碼段僅能有一個線程執(zhí)行Fortran:!$OMP CRITICAL (name) block!$OMP END CRITICAL (name)C/C+:#pragma omp critical (name) structure block說明Critical制導(dǎo)在某一時刻僅能被一個線程執(zhí)

33、行;2022/8/1845Critical制導(dǎo)可用來保護(hù)對共享變量的修改;在Fortran中,前后兩個name必須一致;如果name被省略,一個空(null)的name被假定。例:下面使用了一個未命名的臨界段。#pragma omp critical if(maxnew_value) max=new_value下面使用了一個命名的臨界段。#pragma omp critical (maxvalue) if(maxnew_value) max=new_value使用命名臨界段時,應(yīng)用程序可以有多個臨界段2022/8/1846通過private子句和critical 制導(dǎo)計(jì)算pi值#include

34、 static long num_steps = 100000; double step; #define NUM_THREADS 4 void main () int i; double x, sum, pi=0.0,start_time, end_time; step = 1.0/(double) num_steps; omp_set_num_threads(NUM_THREADS) start_time=omp_get_wtime(); #pragma omp parallel private (x, sum) id = omp_get_thread_num(); for (i=id,s

35、um=0.0;i num_steps;i=i+NUM_THREADS) x = (i+0.5)*step; sum += 4.0/(1.0+x*x); #pragma omp critical pi += sum; end_time=omp_get_wtime(); printf(“Pi=%fn Running time n”, pi, end_time-start_time);2022/8/1847保存共享變量:ATOMIC制導(dǎo)ATOMIC編譯制導(dǎo)表明一個特殊的存儲單元只能原子的更新,而不允許讓多個線程同時去寫主要用來保證操作被安全的執(zhí)行。Fortran:! $OMP ATOMIC stat

36、ementC/C+:#pragma omp atomic statement說明在fortran中,statement必須是下列形式之一: x=x op expr、 x=expr op x 、x=intr(x, expr)或x=intr(expr,x)。 其中: op是+、- 、 * 、/ 、.and. 、 .or. 、.eqv. 、或.neqv. 之一; intr是MAX 、 min 、 IAND 、 IOR或IEOR之一。 2022/8/1848在C/C+中,statement必須是下列形式之一: x binop=expr、 x+ 、 x- 、 +x 、 或-xx 。 其中:binop是二

37、元操作符:+、- 、 * 、 / 、& 、 、 之一。ATOMIC編譯指導(dǎo)的好處是允許并行的更新數(shù)組內(nèi)的不同元素;而使用臨界值時數(shù)組元素的更新是串行的; 無論何時,當(dāng)需要在更新共享存儲單元的語句中避免數(shù)據(jù)競爭,應(yīng)該先使用atomic,然后再使用臨界段。2022/8/1849LOCK 例程一個鎖是一個特殊的變量,它被一個線程設(shè)定,而別的線程僅能在設(shè)定鎖的線程解除鎖后才能設(shè)定鎖Fortran:Subroutine OMP_INIT_LOCK(VAR)Subroutine OMP_SET_LOCK(VAR)LOGICAL FUNCTION OMP_TEST_LOCK(VAR)Subroutine O

38、MP_UNSET_LOCK(VAR)Subroutine OMP_DESTROY_LOCK(VAR)其中變量是一個作為地址的整數(shù)2022/8/1850C/C+:#includevoid omp_init_lock(omp_lock_t *lock);void omp_set_lock(omp_lock_t *lock);int omp_test_lock(omp_lock_t *lock);void omp_unset_lock(omp_lock_t *lock);void omp_detroy_lock(omp_lock_t *lock);2022/8/1851例子 call omp_ini

39、t_lock(ilock) !$OMP PARALLEL SHARED(ilock) . do while ( .not. omp_test_lock(ilock) call do_something_else() end do call work() call omp_unset_lock(ilock) . !$OMP END PARALLEL 說明:鎖在使用前需要進(jìn)行初始化;不再使用時要解鎖。 2022/8/1852FLUSH制導(dǎo)FLUSH語句是用來確保執(zhí)行中存儲器中的數(shù)據(jù)一致的同步點(diǎn)。保證一個變量從內(nèi)存中的讀/寫Fortran:!$OPM FLUSH(list)C/C+:#prgma o

40、mp flush (list)2022/8/1853Run-Time routines2022/8/1854運(yùn)行庫函數(shù)OpenMP標(biāo)準(zhǔn)定義了一個應(yīng)用程序編程接口來調(diào)用庫中的多個函數(shù)。有時需要得到線程數(shù)和線程號,這在控制不同線程執(zhí)行不同的功能代碼時特別有用。得到線程隊(duì)列中的線程數(shù)Fortran: interger function OMP_GET_NUM_THREADS ()C/C+:#include int omp_get_num_threads() 2022/8/1855得到執(zhí)行線程的線程號:Fortran:Interger function OMP_GET_THREAD_NUM ()C/C

41、+:#include int omp_get_thread_num()2022/8/1856設(shè)定執(zhí)行線程的數(shù)量使用運(yùn)行庫函數(shù): Fortran: routine OMP_SET_NUM_THREADS ( ) C/C+: #include omp_set_num_threads()在制導(dǎo)語句中通過 OMP_NUM_THREADS設(shè)定。 通過環(huán)境變量OMP_NUM_THREADS 設(shè)定。2022/8/1857時間函數(shù)return current wall clock time (relative to arbitrary origin) Fortran: DOUBLE PRECISION FUN

42、CTION OMP_GET_WTIME()C/C+: double omp_get_wtime(void); return clock precision Fortran: DOUBLE PRECISION FUNCTION OMP_GET_WTICK()C/C+: double omp_get_wtick(void);2022/8/1858OpenMP環(huán)境變量2022/8/1859環(huán)境變量OpenMP提供了4個環(huán)境變量用來控制并行代碼的執(zhí)行 設(shè)定線程數(shù)環(huán)境變量: 例如: 1. OMP_NUM_THREADS:設(shè)定最大線程數(shù)。 setenv OMP_NUM_THREADS 4 2. OMP_S

43、CHEDULE:設(shè)定DO/for循環(huán)調(diào)度方式環(huán)境變量。 setevn OMP_SCHEDULE “DYNAMIC,4” 2022/8/1860 3. OMP_DYNAMIC:確定是否動態(tài)設(shè)定并行域執(zhí)行的線程數(shù),其值為FALSE或TRUE。 setevn OMP_DYNAMIC TRUE 4.OMP_NESTED:確定是否可以并行嵌套。 setenv OMP_NESTED TURE2022/8/1861NUM_THREADS子句在 OpenMP 2.0 (Fortran 、 C/C+) 中提供了 NUM_THREADS 子句設(shè)定線程數(shù)。例子!$OMP PARALLEL DO NUM_THREAD

44、S(4) DO J = 1,N A(I,J) = B(I,J) !$OMP END DO 說明: 在NUM_THREADS中提供的值將取代環(huán)境變量OMP_NUM_THREADS 的值(或由 omp_set_num_threads()設(shè)定的值 )2022/8/1862OpenMP并行注意的問題數(shù)據(jù)競爭問題;線程間同步;并行執(zhí)行的程序比例及其可擴(kuò)展性;共享內(nèi)存或偽共享內(nèi)存引起的訪存沖突;在DO/for循環(huán)中插入OpenMP指導(dǎo)前,首先要解決的問題是檢查并重構(gòu)熱點(diǎn)循環(huán),確保沒有循環(huán)迭代相關(guān);優(yōu)良的并行算法和精心調(diào)試是好的性能的保證,糟糕的算法即使使用手工優(yōu)化的匯編語言來實(shí)現(xiàn),也無法獲得好的性能;創(chuàng)建

45、在單核或單處理器上出色運(yùn)行的程序同創(chuàng)建在多核或單處理器上出色運(yùn)行的程序是不同的;可以借助一些工具,例Intel VtuneTM性能分析工具,其提供了一個Intel線程監(jiān)測器。 2022/8/1863實(shí)例1:蒙特卡羅算法利用蒙特卡羅算法計(jì)算半徑為1單元的球體體積:(下面為相應(yīng)的串行代碼) #include #include #include int main() long long max=10000000; long long i,count=0; double x,y,z,bulk,start_time,end_time; time_t t; start_time=clock(); / 產(chǎn)生

46、以當(dāng)前時間開始的隨機(jī)種子 srand(unsigned) time(&t); for(i=0;imax;i+) x=rand(); x=x/32767; y=rand(); y=y/32767; z=rand(); z=z/32767; if(x*x+y*y+z*z)=1) count+; bulk=8*(double(count)/max); end_time= clock(); printf(”Sphere bulk is %f n“, bulk); printf(“Running time is %f n“, end_time-start_time); return 0;2022/8/1

47、864OpenMP Parallel for with a reduction #include #include #include #include int main() long long max=10000000; long long i,count=0; double x,y,z,bulk,start_time,end_time; time_t t; start_time=omp_get_wtime(); /產(chǎn)生以當(dāng)前時間開始的隨機(jī)種子 srand(unsigned) time(&t); #pragma omp parallel for private(x,y,z) reduction

48、(+:count) for(i=0;imax;i+) x=rand(); x=x/32767; y=rand(); y=y/32767; z=rand(); z=z/32767; if(x*x+y*y+z*z)=1) count+; bulk=8*(double(count)/max); end_time=omp_get_wtime(); printf(”Sphere bulk is %f n“, bulk); printf(“Running time is %f n“, end_time-start_time); return 0;2022/8/1865作業(yè) 1. 循環(huán)是否可以直接并行do

49、i=2,n a(i)=2*a(i-1) end do ix = base do i=1,n a(ix) = a(ix)*b(i) ix = ix + stride end do do i=1,n b(i)= (a(i)-a(i-1)*0.5 end do 2.上機(jī)調(diào)試培訓(xùn)內(nèi)容中提供的求解pi的各OpenMP并行程序。3.編寫一個矩陣-向量相乘的 OpenMP并行程序。4.分析critical、atomic、lock、flush的用法2022/8/1866設(shè)定線程個數(shù)子句:num_threadsnum_threads子句用來指定并行域內(nèi)使用線程的個數(shù),隨后的其它并行域不受此影響。例: #incl

50、udeomp.h #includestdio.h“ main() omp_set_num_threads(4); #pragma omp parallel num_threads(2) printf(“my thead number is %dn,omp_get_thread_num(); num_threads子句的優(yōu)先權(quán)高于庫例程omp_set_num_threads和環(huán)境變量NMP_NUM_THREADS。67x0=10;for(i=0;in;i+) for(j=1;i4;j+) xj=i+xj-1; yi=x1-x3; firstprivate子句該子句使并行域內(nèi)私有變量的初始值通過master線程的值初始化。格式: firstprivate(變量列表)例:x0=10;#pragma ompparallel for private(j) firstprivate(x)for(i=0;in;i+) for(j=1;i4;j+) xj=i+xj-1;

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論