并行計(jì)算課程設(shè)計(jì)報(bào)告.doc_第1頁
并行計(jì)算課程設(shè)計(jì)報(bào)告.doc_第2頁
并行計(jì)算課程設(shè)計(jì)報(bào)告.doc_第3頁
并行計(jì)算課程設(shè)計(jì)報(bào)告.doc_第4頁
并行計(jì)算課程設(shè)計(jì)報(bào)告.doc_第5頁
已閱讀5頁,還剩41頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

并行計(jì)算與多核多線程技術(shù)課程報(bào)告 專業(yè) 班級 學(xué)號 姓名 成績 _ 年 月 日課程報(bào)告要求手寫內(nèi)容:設(shè)計(jì)目的、意義,設(shè)計(jì)分析,方案分析,功能模塊實(shí)現(xiàn),最終結(jié)果分析,設(shè)計(jì)體會等。 允許打印內(nèi)容:設(shè)計(jì)原理圖等圖形、圖片,電路圖,源程序。硬件類的設(shè)計(jì),要有最終設(shè)計(jì)的照片圖;軟件類設(shè)計(jì),要有各個(gè)功能模塊實(shí)現(xiàn)的界面圖、輸入輸出界面圖等。評 價(jià)理論基礎(chǔ)實(shí)踐效果(正確度/加速比)難度工作量獨(dú)立性目 錄1. 設(shè)計(jì)目的、意義(功能描述)12. 方案分析(解決方案)13. 設(shè)計(jì)分析13.1 串行算法設(shè)計(jì)13.2 并行算法設(shè)計(jì)13.3 理論加速比分析24. 功能模塊實(shí)現(xiàn)與最終結(jié)果分析24.1 基于OpenMP的并行算法實(shí)現(xiàn)24.1.1 主要功能模塊與實(shí)現(xiàn)方法24.1.2 實(shí)驗(yàn)加速比分析24.2 基于MPI的并行算法實(shí)現(xiàn)24.2.1 主要功能模塊與實(shí)現(xiàn)方法24.2.2 實(shí)驗(yàn)加速比分析24.3 基于Java的并行算法實(shí)現(xiàn)34.3.1 主要功能模塊與實(shí)現(xiàn)方法34.3.2 實(shí)驗(yàn)加速比分析34.4 基于Windows API的并行算法實(shí)現(xiàn)34.4.1 主要功能模塊與實(shí)現(xiàn)方法34.4.2 實(shí)驗(yàn)加速比分析34.5 基于.net的并行算法實(shí)現(xiàn)34.5.1 主要功能模塊與實(shí)現(xiàn)方法34.5.2 實(shí)驗(yàn)加速比分析34.6并行計(jì)算技術(shù)在實(shí)際系統(tǒng)中的應(yīng)用44.6.1 主要功能模塊與實(shí)現(xiàn)方法44.6.2 實(shí)驗(yàn)加速比分析55. 設(shè)計(jì)體會56. 附錄66.1 基于OpenMP的并行程序設(shè)計(jì)66.1.1 代碼及注釋66.1.2 執(zhí)行結(jié)果截圖66.1.3 遇到的問題及解決方案66.2 基于MPI的并行程序設(shè)計(jì)76.1.1 代碼及注釋76.2.2 執(zhí)行結(jié)果截圖76.2.3 遇到的問題及解決方案76.3 基于Java的并行程序設(shè)計(jì)86.3.1 代碼及注釋86.3.2 執(zhí)行結(jié)果截圖86.3.3 遇到的問題及解決方案96.4 基于Windows API的并行程序設(shè)計(jì)96.4.1 代碼及注釋96.4.2 執(zhí)行結(jié)果截圖106.4.3 遇到的問題及解決方案106.5 基于.net的并行程序設(shè)計(jì)116.5.1 代碼及注釋116.5.2 執(zhí)行結(jié)果截圖116.5.3 遇到的問題及解決方案116.6并行計(jì)算技術(shù)在實(shí)際應(yīng)用系統(tǒng)的應(yīng)用156.6.1 代碼及注釋156.6.2 執(zhí)行結(jié)果截圖156.6.3 遇到的問題及解決方案151. 設(shè)計(jì)目的、意義(功能描述)設(shè)計(jì)一個(gè)計(jì)算向量夾角的WinForm窗體應(yīng)用,用戶只需要在窗體上輸入向量的維度,系統(tǒng)隨機(jī)產(chǎn)生兩個(gè)向量并將計(jì)算結(jié)果顯示在窗體上。求兩個(gè)n維向量的夾角,要用到求向量夾角的數(shù)學(xué)公式,當(dāng)向量維度較小時(shí)計(jì)算量不大,而當(dāng)維度過大時(shí)特別是百萬級甚至千萬級別的時(shí)候計(jì)算量就很大了,用并行計(jì)算求向量夾角,可以將任務(wù)分配給多個(gè)處理器,減小運(yùn)算時(shí)間。所以要設(shè)計(jì)一個(gè)并行計(jì)算夾角的方法,提高計(jì)算速度,把并行和串行計(jì)算時(shí)間做個(gè)比較顯示在窗體上。窗體應(yīng)用比控制臺程序更方便用戶操作,簡單直觀,頁面也更加友好。2. 方案分析(解決方案)定義兩個(gè)數(shù)組分別存放兩個(gè)向量,用for循環(huán)將產(chǎn)生的隨機(jī)數(shù)賦值給數(shù)組。假設(shè)有兩個(gè)向量X,Y X=(x1,x2,xn),Y=(y1,y2,yn)計(jì)算X,Y夾角的公式是:cos(X,Y)=XY/(|X|Y|)=(x1y1+x2y2+xnyn)/(x1+x2+xn)1/2(y1+y2+yn)1/2。由3個(gè)for循環(huán)分別實(shí)現(xiàn)求向量積和兩個(gè)向量的模,最后用公式計(jì)算即可。3. 設(shè)計(jì)分析3.1 串行算法設(shè)計(jì)輸入:向量的維度n輸出:兩個(gè)隨機(jī)向量的夾角syy_angleBegin給存放向量的數(shù)組動態(tài)分配內(nèi)存空間For i=0 to i=n-1 do 產(chǎn)生隨機(jī)數(shù)給數(shù)組x賦值endForFor i=0 to i=n-1 do產(chǎn)生隨機(jī)數(shù)給數(shù)組y賦值endForFor i=0 to i=n-1 do 計(jì)算向量積endForFor i=0 to i=n-1 do計(jì)算向量X模endForFor i=0 to i=n-1 do 計(jì)算向量Y模endFor利用公式計(jì)算夾角End3.2 并行算法設(shè)計(jì)輸入:向量的維度n輸出:兩個(gè)隨機(jī)向量的夾角syy_angleBegin給存放向量的數(shù)組動態(tài)分配內(nèi)存空間For i=0 to i=n-1 do 產(chǎn)生隨機(jī)數(shù)給數(shù)組x賦值endForFor i=0 to i=n-1 do產(chǎn)生隨機(jī)數(shù)給數(shù)組y賦值endFor3個(gè)for循環(huán)串行執(zhí)行,每個(gè)for循環(huán)由p個(gè)核并行執(zhí)行:p個(gè)核同時(shí)執(zhí)行第一個(gè)for循環(huán)For i=0 to i=n-1 do 計(jì)算向量積endForp個(gè)核同時(shí)執(zhí)行第二個(gè)for循環(huán)For i=0 to i=n-1 do計(jì)算向量X模endForp個(gè)核同時(shí)執(zhí)行第三個(gè)for循環(huán)For i=0 to i=n-1 do 計(jì)算向量Y模endFor利用公式計(jì)算夾角End3.3 理論加速比分析設(shè)加速比為S,串行運(yùn)行時(shí)間為Ts,并行的運(yùn)行時(shí)間為Tp。假設(shè)一次運(yùn)算作為一個(gè)時(shí)間單位,對于串行算法來說其時(shí)間復(fù)雜度為O(n) 即Ts=O(n) ,對于并行算法來說,由于有p個(gè)處理器同時(shí)運(yùn)行,則其時(shí)間復(fù)雜度為O(n/p) 即Tp=O(n/p) ,所以理論加速比S=Ts/Tp=O(n)/O(n/p)=p。4. 功能模塊實(shí)現(xiàn)與最終結(jié)果分析4.1 基于OpenMP的并行算法實(shí)現(xiàn)4.1.1 主要功能模塊與實(shí)現(xiàn)方法1:向量x,y賦值,用產(chǎn)生的隨機(jī)數(shù)對存放向量的數(shù)組賦值,得到兩個(gè)隨機(jī)向量srand(int)time(0);/數(shù)組X賦值for(i=0;in;i+) j=(int)(100*rand()/(RAND_MAX+1.0); /隨機(jī)產(chǎn)生的數(shù)xi=j; /數(shù)組Y賦值for(i=0;in;i+) j=(int)(100*rand()/(RAND_MAX+1.0); /隨機(jī)產(chǎn)生的數(shù)yi=j; 2:計(jì)算向量積,向量x,y的模用并行實(shí)現(xiàn)。設(shè)置兩個(gè)線程,用reduction實(shí)現(xiàn)并行計(jì)算,兩個(gè)線程都會創(chuàng)建一個(gè)reduction變量的私有副本,在OPENMP區(qū)域結(jié)束后,將各個(gè)線程的計(jì)算結(jié)果相加賦值給原來的變量。#pragma omp parallel for reduction(+:syy_outer_product)for(i=0;in;i+)syy_outer_product=syy_outer_product+xi*yi;/計(jì)算向量積計(jì)算向量X,Y的模方法與上面類似4.1.2 實(shí)驗(yàn)加速比分析線程數(shù)設(shè)置為2時(shí),向量維數(shù)小時(shí),由于精度問題,運(yùn)行時(shí)間顯示為0,加速比無法計(jì)算。向量維數(shù)到達(dá)百萬級以上,加速比介于1到2之間,根據(jù)向量維數(shù)的變化,加速比有一定的變化但不會超過范圍。4.2 基于MPI的并行算法實(shí)現(xiàn)4.2.1 主要功能模塊與實(shí)現(xiàn)方法使用MPI群集通信,由0進(jìn)程接收輸入的數(shù)組長度n,給數(shù)組動態(tài)分配內(nèi)存后,用產(chǎn)生的隨機(jī)數(shù)給數(shù)組賦值。用MPI_Bcast先將數(shù)組長度廣播給其他進(jìn)程,由其他進(jìn)程給數(shù)組動態(tài)分配內(nèi)存后,再將數(shù)組值廣播給其他進(jìn)程。求向量積,向量模的for由多個(gè)進(jìn)程同時(shí)執(zhí)行,將0到n-1次循環(huán)分配給P個(gè)進(jìn)程,每個(gè)進(jìn)程從i=myid開始執(zhí)行,循環(huán)一次i加進(jìn)程數(shù)。將每個(gè)進(jìn)程的計(jì)算結(jié)果用MPI_Reduce函數(shù)規(guī)約。1:由0進(jìn)程進(jìn)行隨機(jī)數(shù)組動態(tài)分配內(nèi)存和賦值操作if(myid=0)/為數(shù)組x,y動態(tài)分配空間x = (int*)malloc(n * sizeof(int);y = (int*)malloc(n * sizeof(int);srand(int)time(0);/數(shù)組X賦值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /隨即產(chǎn)生的數(shù)xi=j; 數(shù)組y賦值同上starttime=MPI_Wtime();2:用MPI_Bcast()函數(shù)將數(shù)組長度和值廣播給其他進(jìn)程MPI_Bcast(&n,1,MPI_LONG,0,MPI_COMM_WORLD);/將n值廣播出去MPI_Bcast(x,n,MPI_INT,0,MPI_COMM_WORLD);/將x值廣播出去MPI_Bcast(y,n,MPI_INT,0,MPI_COMM_WORLD);/將y值廣播出去3:用MPI_Reduce()函數(shù)對各個(gè)進(jìn)程的計(jì)算結(jié)果規(guī)約MPI_Reduce(&my_product,&syy_outer_product,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); MPI_Reduce(&my_mol_x,&syy_mol_x,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);MPI_Reduce(&my_mol_y,&syy_mol_y,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);4:多個(gè)進(jìn)程同時(shí)執(zhí)行for循環(huán)for(i=syy_myid;in;i+=syy_numprocs) product+=xi*yi;/計(jì)算向量積計(jì)算向量x,y模與上面類似5:串行部分由0進(jìn)程完成,在執(zhí)行完并行計(jì)算后,再由0進(jìn)程單獨(dú)完成串行操作. if(syy_myid=0 )里執(zhí)行的串行操作4.2.2 實(shí)驗(yàn)加速比分析并行時(shí)間比串行時(shí)間要長,加速比低于1,MPI并行是進(jìn)程間相互通信傳遞數(shù)據(jù)。設(shè)置兩個(gè)進(jìn)程時(shí),在0進(jìn)程里輸入向量維度,由0進(jìn)程對向量數(shù)組賦值。再將n值和x,y動態(tài)數(shù)組廣播給其他進(jìn)程。串行計(jì)算只有0進(jìn)程獨(dú)立完成,可能是進(jìn)程間通信過多使并行額外開銷太大。4.3 基于Java的并行算法實(shí)現(xiàn)4.3.1 主要功能模塊與實(shí)現(xiàn)方法1:繼承Thread類,創(chuàng)建兩個(gè)線程thread1,thread2。用start方法開始線程。使用join()方法等待線程結(jié)束后再繼續(xù)執(zhí)行。javaand thread1=new javaand(0,n,x,y);javaand thread2=new javaand(1,n,x,y);startTime=System.currentTimeMillis();thread1.start();thread2.start();thread1.join();thread2.join();2:兩個(gè)線程同時(shí)執(zhí)行run函數(shù),thread1循環(huán)從0到n-1,每次循環(huán)i加2,thread2循環(huán)從1到n-1,每次循環(huán)i加2.最后兩個(gè)線程的計(jì)算結(jié)果相加public void run()for(long i=start;iend;i+=2)syy_outer_product+=x(int)i*y(int)i;/計(jì)算向量積for(long i=start;iend;i+=2)syy_mol_x+=x(int)i*x(int)i;/計(jì)算向量X模for(long i=start;iend;i+=2)syy_mol_y+=y(int)i*y(int)i;/計(jì)算向量Y模3:用count函數(shù)實(shí)現(xiàn)串行計(jì)算,循環(huán)從0到n-1,每次循環(huán)i加1.循環(huán)部分代碼與run方法中類似。分別用三個(gè)循環(huán)計(jì)算向量積,向量X,Y模后再根據(jù)公式計(jì)算向量夾角,最后返回運(yùn)算結(jié)果。4.3.2 實(shí)驗(yàn)加速比分析數(shù)據(jù)量較小時(shí),串并行顯示的時(shí)間都為0,因此無法計(jì)算加速比,當(dāng)數(shù)據(jù)量較大時(shí)加速比控制在1-2之間。輸入向量的維度超過100000000時(shí),出現(xiàn)內(nèi)存溢出,無法計(jì)算加速比。數(shù)組長度定義過大時(shí),程序消耗內(nèi)存過大會出現(xiàn)內(nèi)存溢出,即使是修改JVM -Xmx 參數(shù)后,向量維度也不能超過1000000004.4 基于Windows API的并行算法實(shí)現(xiàn)4.4.1 主要功能模塊與實(shí)現(xiàn)方法1:創(chuàng)建兩個(gè)線程thread1 ,thread2,分別指定線程函數(shù)為ThreadOne ThreadTwo創(chuàng)建成功后返回線程的句柄,等待兩個(gè)線程計(jì)算完后將兩個(gè)線程的執(zhí)行結(jié)果相加HANDLE thread1=CreateThread(NULL,0,ThreadOne,NULL,0,NULL);HANDLE thread2=CreateThread(NULL,0,ThreadTwo,NULL,0,NULL);WaitForMultipleObjects(2,finish,true,INFINITE);for(int i=0;i2;i+)syy_outer_product+=producti;syy_mol_x+=mol_xi; syy_mol_y+=mol_yi;2:并行線程函數(shù),將n次循環(huán)分成兩部分,線程函數(shù)ThreadOne執(zhí)行前半部分操作,函數(shù)ThreadTwo執(zhí)行后半部分操作Thread1線程函數(shù)負(fù)責(zé)for循環(huán)從0到(n/2)-1:DWORD WINAPI ThreadOne(LPVOID param) Thread2線程函數(shù)負(fù)責(zé)for循環(huán)從n/2到n-1 :DWORD WINAPI ThreadTwo(LPVOID param)3:線程函數(shù)ThreadThree作為單線程執(zhí)行,for循環(huán)從0到n-1DWORD WINAPI ThreadThree(LPVOID param)4.4.2 實(shí)驗(yàn)加速比分析串行和并行運(yùn)算結(jié)果相同,但并行比串行時(shí)間大。從理論上分析,兩個(gè)線程同時(shí)執(zhí)行for循環(huán),加速比應(yīng)該在1-2之間,而實(shí)際情況是并行比串行時(shí)間還久。WaitForMultipleObjects(2,finish,true,INFINITE);這句運(yùn)行時(shí)間長,使用WaitForMultipleObjects函數(shù)是讓線程進(jìn)入等待狀態(tài),直到finishi指向的內(nèi)核對象都變?yōu)橐淹ㄖ獱顟B(tài)。先完成工作的處理器要等待未完成工作的處理器,處理器空閑時(shí)間太大可能會造成并行比串行時(shí)間大。4.5 基于.net的并行算法實(shí)現(xiàn)4.5.1 主要功能模塊與實(shí)現(xiàn)方法1:創(chuàng)建ThreadStart代理,即thread1 ,thread2。指定Work類的sum函數(shù)作為兩個(gè)線程執(zhí)行的線程函數(shù)。將thread1,thread2代理傳遞給Thread類的構(gòu)造函數(shù),最后調(diào)用Thread類的Start方法開啟線程。Join方法可以保證應(yīng)用程序域等待異步線程結(jié)束后才終止運(yùn)行。Work work1 = new Work(0,n,x,y);ThreadStart thread1 = new ThreadStart(work1.Sum); Thread newthread1 = new Thread(thread1);Work work2 = new Work(1,n,x,y);ThreadStart thread2 = new ThreadStart(work2.Sum);Thread newthread2 = new Thread(thread2);2:用于實(shí)現(xiàn)并行計(jì)算的Work類的Sum函數(shù)。newthread1執(zhí)行的循環(huán)是從0到n-1,每次循環(huán)i加2。newthread2執(zhí)行的循環(huán)是從1到n-1,每次循環(huán)i加2。計(jì)算向量積的for循環(huán)如下:for (long i = start; i end; i += 2) syy_outer_product += xi * yi;/計(jì)算向量積 3:調(diào)用Work類的sumto函數(shù)實(shí)現(xiàn)串行計(jì)算,并返回計(jì)算得到的夾角。用3個(gè)for循環(huán)分別計(jì)算向量積和x,y的模,循環(huán)從0到n-1,每次i加1,最后用公式計(jì)算夾角。4.5.2 實(shí)驗(yàn)加速比分析設(shè)置兩個(gè)線程同時(shí)計(jì)算,能得到較理想的加速比,數(shù)據(jù)量為十幾時(shí),加速比在1.8左右,數(shù)據(jù)量達(dá)到10000000000時(shí),加速比能接近1.9.從總體的運(yùn)行結(jié)果看,加速比在1.7到1.9之間,符合理論加速比的分析。4.6 并行計(jì)算技術(shù)在實(shí)際系統(tǒng)中的應(yīng)用4.6.1 主要功能模塊與實(shí)現(xiàn)方法1:確認(rèn)按鈕點(diǎn)擊事件函數(shù),當(dāng)點(diǎn)擊確認(rèn)按鈕后從文本框中獲取向量的維度,傳遞給count函數(shù):private void confirm_Click(object sender, EventArgs e)2:從窗體中獲取向量維度后用count函數(shù)計(jì)算夾角,并把結(jié)果返回給窗體。用并行和串行方法計(jì)算的代碼全部放在count函數(shù)里進(jìn)行public void count(long n)3:創(chuàng)建兩個(gè)線程實(shí)現(xiàn)并行計(jì)算創(chuàng)建兩個(gè)線程代理thread1 ,thread2指定線程函數(shù)Work類里的Sum函數(shù),然后將ThreadStart代理傳遞給Thread類的構(gòu)造函數(shù)Work work1 = new Work(0,n,x,y);ThreadStart thread1 = new ThreadStart(work1.Sum); Thread newthread1 = new Thread(thread1);Work work2 = new Work(1,n,x,y);ThreadStart thread2 = new ThreadStart(work2.Sum);Thread newthread2 = new Thread(thread2);4:用于實(shí)現(xiàn)并行計(jì)算的Work類的Sum函數(shù)。newthread1執(zhí)行的循環(huán)是從0到n-1,每次循環(huán)i加2。newthread2執(zhí)行的循環(huán)是從1到n-1,每次循環(huán)i加2。計(jì)算向量積的for循環(huán)如下:for (long i = start; i end; i += 2) syy_outer_product += xi * yi;/計(jì)算向量積 5:調(diào)用Work類的sumto函數(shù)實(shí)現(xiàn)串行計(jì)算,并返回計(jì)算得到的夾角。用3個(gè)for循環(huán)分別計(jì)算向量積和x,y的模,循環(huán)從0到n-1,每次i加1,最后用公式計(jì)算夾角。4.6.2 實(shí)驗(yàn)加速比分析當(dāng)數(shù)據(jù)量較小時(shí)加速比接近于1,比較小。當(dāng)數(shù)據(jù)量大的時(shí)候,加速比有時(shí)會超過2,甚至接近于3,與理論分析的加速比有出入。可能跟WinForm窗體運(yùn)行環(huán)境有關(guān),用C#語言寫的程序占用內(nèi)存小加速比高。5. 設(shè)計(jì)體會這次課程設(shè)計(jì)是用了5種不同的方法實(shí)現(xiàn)求n維隨機(jī)向量的夾角,在具體的編程過程中遇到了很多問題,在解決問題過程中也有不少收獲,下面我就這五種實(shí)現(xiàn)方法談?wù)勎业脑O(shè)計(jì)體會。 用OpenMP編程時(shí)為了解決數(shù)據(jù)競爭的問題,我使用了reduction字句,在進(jìn)入并行區(qū)域后兩個(gè)線程就有各自的變量的副本,只要變量不公用,就不存在數(shù)據(jù)競爭的問題。OpenMP的編程是在parallel并行區(qū)內(nèi)并行計(jì)算,我覺得相比其他四個(gè)編程方法這個(gè)更簡單。 在MPI編程中,我遇到了最大的問題是不知道如何廣播動態(tài)數(shù)組,后來上網(wǎng)查詢,找到了一個(gè)解決方案是先將數(shù)組長度廣播出去,然后非0進(jìn)程動態(tài)非配空間后再廣播該數(shù)組。 用java語言編寫程序時(shí),很多程序語言需要利用外部的線程軟件包來實(shí)現(xiàn)多線程,而java語言則內(nèi)在支持多線程,它的所有類都是在多線程的思想下定義的。Java編程中實(shí)現(xiàn)多線程有兩種辦法:一種是用戶在自己定義的類中使用Runnable接口,另一種是繼承Thread類。我用的就是第二種方法,在run函數(shù)中實(shí)現(xiàn)并行,在count函數(shù)中實(shí)現(xiàn)串行。 .net編程有很多地方與java相似,用兩個(gè)線程做并行計(jì)算,都要先創(chuàng)建進(jìn)程,但.net創(chuàng)建線程首先需要創(chuàng)建ThreadStart 代理,指定線程執(zhí)行的線程函數(shù),然后再創(chuàng)建Thread類線程,將ThreadStart代理傳遞給Thread類的構(gòu)造函數(shù)。線程函數(shù)有點(diǎn)類似于java Thread類里的run函數(shù),都是兩個(gè)線程同時(shí)執(zhí)行的函數(shù)。 Win32API編程不需要配置編程環(huán)境,應(yīng)用程序只需要調(diào)用相關(guān)的函數(shù)就行,Win32 API提供了一系列處理線程的函數(shù)接口,向應(yīng)用程序提供多線程的功能。總之,每種實(shí)現(xiàn)方法都各有特點(diǎn)。用不同的語言實(shí)現(xiàn)同一種算法,在具體的編程過程中也會有細(xì)小的差異,每一次修正錯(cuò)誤都是一次學(xué)習(xí)。6. 附錄6.1 基于OpenMP的并行程序設(shè)計(jì)6.1.1 代碼及注釋(變量名 名字首字母 開頭)#include stdafx.h#include #include #include #include #include #include #define NUM_THREADS 2int _tmain(int argc, _TCHAR* argv)int j; /隨機(jī)數(shù)long long i;long long n;long double syy_outer_product=0,syy_mol_x=0,syy_mol_y=0,syy_angle;/向量積clock_t t1,t2,t3,t4; printf(兩條n維隨即向量的夾角串并行計(jì)算n); printf(請輸入向量的維度:n);scanf(%lld,&n);/為數(shù)組x,y動態(tài)分配空間int *x = (int*)malloc(n * sizeof(int);int *y = (int*)malloc(n * sizeof(int);srand(int)time(0);/數(shù)組X賦值for(i=0;in;i+) j=(int)(100*rand()/(RAND_MAX+1.0); /隨即產(chǎn)生到的數(shù)xi=j; /數(shù)組Y賦值for(i=0;in;i+) j=(int)(100*rand()/(RAND_MAX+1.0); /隨即產(chǎn)生到的數(shù)yi=j; /* 串行區(qū)域 */ t1=clock();for(i=0;in;i+)syy_outer_product=syy_outer_product+xi*yi;/計(jì)算向量積for(i=0;in;i+)syy_mol_x=syy_mol_x+xi*xi;/計(jì)算向量X模for(i=0;in;i+)syy_mol_y=syy_mol_y+yi*yi;/計(jì)算向量Y模t2=clock();t3=t2-t1;/串行時(shí)間syy_mol_x=sqrt(syy_mol_x);syy_mol_y=sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);printf(隨即產(chǎn)生兩個(gè)向量,向量的夾角cos(x,y)=%fn,syy_angle);printf(串行時(shí)間=%dn,(t2-t1); syy_mol_x=0;syy_mol_y=0;syy_outer_product=0;omp_set_num_threads(NUM_THREADS);/設(shè)置線程數(shù)t1=clock();/* 并行區(qū)域 */#pragma omp parallel for reduction(+:syy_outer_product)for(i=0;in;i+)syy_outer_product=syy_outer_product+xi*yi;/計(jì)算向量積#pragma omp parallel for reduction(+:syy_mol_x)for(i=0;in;i+)syy_mol_x=syy_mol_x+xi*xi;/計(jì)算向量X模#pragma omp parallel for reduction(+:syy_mol_y)for(i=0;in;i+)syy_mol_y=syy_mol_y+yi*yi;/計(jì)算向量Y模t2=clock();t4=t2-t1;/并行時(shí)間syy_mol_x=sqrt(syy_mol_x);syy_mol_y=sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);printf(隨即產(chǎn)生兩個(gè)向量,向量的夾角cos(x,y)=%fn,syy_angle);printf(并行時(shí)間=%dn,(t2-t1);printf(加速比=%fn,(float)t3/t4);free (x);free(y);system(pause);return 0;6.1.2 執(zhí)行結(jié)果截圖(體現(xiàn)串行時(shí)間、并行時(shí)間和加速比)(1)小數(shù)據(jù)量驗(yàn)證正確性的執(zhí)行結(jié)果(2)大數(shù)據(jù)量獲得較好加速比的執(zhí)行結(jié)果6.1.3 遇到的問題及解決方案(1)問題一錯(cuò)誤代碼及后果遇到的問題是當(dāng)向量的維度定義超過1億級時(shí)會存在數(shù)組越界,其他沒什么大問題。正確代碼分析6.2 基于MPI的并行程序設(shè)計(jì)6.1.1 代碼及注釋(變量名 名字首字母 開頭)/ syyMPI.cpp : 定義控制臺應(yīng)用程序的入口點(diǎn)。/#include stdafx.h#include mpi.h#include #include #include #include void main(int argc, char* argv)int j; /隨機(jī)數(shù)int syy_myid,syy_numprocs;/線程編號和線程總數(shù) long int i,n;/n為向量的維數(shù) long double product,mol_x,mol_y,my_product,my_mol_x,my_mol_y; long double syy_outer_product,syy_mol_x,syy_mol_y,syy_angle;double starttime,endtime;int *x,*y;MPI_Init(&argc,&argv);/并行開始MPI_Comm_size(MPI_COMM_WORLD,&syy_numprocs);MPI_Comm_rank(MPI_COMM_WORLD,&syy_myid);if(syy_myid=0)printf(請輸入向量的維度:n);fflush(stdout);scanf_s(%ld,&n);/為數(shù)組x,y動態(tài)分配空間x = (int*)malloc(n * sizeof(int);y = (int*)malloc(n * sizeof(int);srand(int)time(0);/數(shù)組X賦值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /隨即產(chǎn)生的數(shù)xi=j; /數(shù)組Y賦值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /隨即產(chǎn)生的數(shù)yi=j;starttime=MPI_Wtime();MPI_Bcast(&n,1,MPI_LONG,0,MPI_COMM_WORLD);/將n值廣播出去if(syy_myid!=0)x = (int*)malloc(n * sizeof(int); y = (int*)malloc(n * sizeof(int);MPI_Bcast(x,n,MPI_INT,0,MPI_COMM_WORLD);/將x值廣播出去MPI_Bcast(y,n,MPI_INT,0,MPI_COMM_WORLD);/將y值廣播出去product=0.0;mol_x=0.0;mol_y=0.0;for(i=syy_myid;in;i+=syy_numprocs) product+=xi*yi;/計(jì)算向量積 for(i=syy_myid;in;i+=syy_numprocs) mol_y+=yi*yi;/計(jì)算向量Y模 for(i=syy_myid;in;i+=syy_numprocs) mol_x+=xi*xi;/計(jì)算向量X模my_product=product;my_mol_x=mol_x;my_mol_y=mol_y;MPI_Reduce(&my_product,&syy_outer_product,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);/將各線程求得的向量積求和MPI_Reduce(&my_mol_x,&syy_mol_x,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);/將各線程求得的向量X模求和MPI_Reduce(&my_mol_y,&syy_mol_y,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);/將各線程求得的向量Y模求和if(syy_myid=0)syy_mol_x=sqrt(syy_mol_x);syy_mol_y=sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);endtime=MPI_Wtime();/并行結(jié)束時(shí)間printf(隨機(jī)產(chǎn)生兩個(gè)向量,向量的夾角cos(x,y)=%fn,syy_angle);printf(并行時(shí)間=%fn,endtime-starttime);/0進(jìn)程做串行部分if(syy_myid=0 )syy_mol_x=0; syy_mol_y=0; syy_outer_product=0; starttime=MPI_Wtime();for(i=0;in;i+) syy_outer_product+=xi*yi;/計(jì)算向量積 for(i=0;in;i+) syy_mol_y+=yi*yi;/計(jì)算向量Y模 for(i=0;in;i+) syy_mol_x+=xi*xi;/計(jì)算向量X模syy_mol_x=sqrt(syy_mol_x);syy_mol_y=sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);endtime=MPI_Wtime();/并行結(jié)束時(shí)間printf(隨機(jī)產(chǎn)生兩個(gè)向量,向量的夾角cos(x,y)=%fn,syy_angle);printf(串行時(shí)間=%fn,endtime-starttime);MPI_Finalize();/并行結(jié)束6.2.2 執(zhí)行結(jié)果截圖(體現(xiàn)串行時(shí)間、并行時(shí)間和加速比)(1) 小數(shù)據(jù)量驗(yàn)證正確性的執(zhí)行結(jié)果進(jìn)程數(shù)設(shè)置為2的運(yùn)行結(jié)果(2)大數(shù)據(jù)量獲得較好加速比的執(zhí)行結(jié)果進(jìn)程數(shù)設(shè)置為2的運(yùn)行結(jié)果進(jìn)程數(shù)設(shè)置為3的運(yùn)行結(jié)果6.2.3 遇到的問題及解決方案(1)問題一錯(cuò)誤代碼及后果printf(請輸入向量的維度:n);scanf(%ld,&n);后果:控制臺沒有任何輸出結(jié)果正確代碼printf(請輸入向量的維度:n);fflush(stdout);scanf_s(%ld,&n);分析在0進(jìn)程中輸入n的值,如果沒有使用fflush(stdout)(清除緩沖區(qū)后將內(nèi)容輸出),控制臺會輸出兩遍而且運(yùn)行不出來結(jié)果,修改后能正確輸出(2)問題二錯(cuò)誤代碼及后果printf(請輸入向量的維度:n);fflush(stdout);scanf_s(%ld,&n);/為數(shù)組x,y動態(tài)分配空間x = (int*)malloc(n * sizeof(int);y = (int*)malloc(n * sizeof(int);srand(int)time(0);/數(shù)組X賦值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /隨即產(chǎn)生的數(shù)xi=j; /數(shù)組Y賦值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /隨即產(chǎn)生的數(shù)yi=j;MPI_Init(&argc,&argv);/并行開始MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Comm_rank(MPI_COMM_WORLD,&myid);if(myid=0)starttime=MPI_Wtime();正確代碼MPI_Init(&argc,&argv);/并行開始MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Comm_rank(MPI_COMM_WORLD,&myid);if(myid=0)printf(請輸入向量的維度:n);fflush(stdout);scanf_s(%ld,&n);/為數(shù)組x,y動態(tài)分配空間x = (int*)malloc(n * sizeof(int);y = (int*)malloc(n * sizeof(int);srand(int)time(0);/數(shù)組X賦值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /隨即產(chǎn)生的數(shù)xi=j; /數(shù)組Y賦值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /隨即產(chǎn)生的數(shù)yi=j;starttime=MPI_Wtime();分析把數(shù)組的賦值放在并行區(qū)域外執(zhí)行,輸出語句會執(zhí)行兩遍,如果由0進(jìn)程對數(shù)組賦值,然后廣播給其他進(jìn)程就能正確執(zhí)行。出現(xiàn)這種情況可能是兩個(gè)進(jìn)程串行的執(zhí)行了輸出語句。(3)問題三錯(cuò)誤代碼及后果MPI_Bcast(&n,1,MPI_LONG,0,MPI_COMM_WORLD);/將n值廣播出去MPI_Bcast(&x,1,MPI_INT,0,MPI_COMM_WORLD);/將x值廣播出去MPI_Bcast(&y,1,MPI_INT,0,MPI_COMM_WORLD);/將y值廣播出去后果:程序執(zhí)行不了,閃退正確代碼MPI_Bcast(&n,1,MPI_LONG,0,MPI_COMM_WORLD);/將n值廣播出去if(myid!=0)x = (int*)malloc(n * sizeof(int); y = (int*)malloc(n * sizeof(int);MPI_Bcast(x,n,MPI_INT,0,MPI_COMM_WORLD);/將x值廣播出去MPI_Bcast(y,n,MPI_INT,0,MPI_COMM_WORLD);/將y值廣播出去分析動態(tài)數(shù)組的廣播:有時(shí)我們要廣播的數(shù)據(jù)長度并不知道,這時(shí)就需要采用動態(tài)分配的方式分配數(shù)據(jù),然后再將其廣播。這里很容易出問題,問題的根本就是MPI程序是分布式程序,即使我們在寫程序時(shí)所有的進(jìn)程都公用相同的變量,但是在不同的進(jìn)程下它們的含義不同。這就會導(dǎo)致有些進(jìn)程的指針變量指向一塊已經(jīng)分配內(nèi)存的空間,但是有些進(jìn)程的指令變量還是空指針。這時(shí)如果不注意,就會導(dǎo)致動態(tài)數(shù)組廣播的失敗。解決辦法是: 0進(jìn)程從用戶讀取一個(gè)長度,然后利用malloc分配空間并賦值,然后將該數(shù)組廣播到其他進(jìn)程。方法是首先廣播數(shù)組的長度,然后讓其他進(jìn)程分配相應(yīng)的內(nèi)存,最后再廣播該數(shù)組。6.3 基于Java的并行程序設(shè)計(jì)6.3.1 代碼及注釋(變量名 名字首字母 開頭)import java.util.Random;import java.util.Scanner;public class javaand extends Thread private long start;private long end;private double syy_outer_product=0,syy_mol_x=0,syy_mol_y=0;private double x,y;public javaand(long start,long end,double x,double y)super();this.start=start;this.end=end;this.x=x;this.y=y;public void run()for(long i=start;iend;i+=2)syy_outer_product+=x(int)i*y(int)i;/計(jì)算向量積for(long i=start;iend;i+=2)syy_mol_x+=x(int)i*x(int)i;/計(jì)算向量X模for(long i=start;iend;i+=2)syy_mol_y+=y(int)i*y(int)i;/計(jì)算向量Y模public double count()double syy_outer_product=0,syy_mol_x=0,syy_mol_y=0,syy_angle;for(long i=start;iend;i+)syy_outer_product+=x(int)i*y(int)i;/計(jì)算向量積for(long i=start;iend;i+)syy_mol_x+=x(int)i*x(int)i;/計(jì)算向量X模for(long i=start;iend;i+)syy_mol_y+=y(int)i*y(int)i;/計(jì)算向量Y模syy_mol_x=Math.sqr

溫馨提示

  • 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)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論