有共享變數時,並行程式就難寫了(已完成)
在前次N王后問題中加入瞭解法的輸出.只有原始的才正確.沒想到其他分佈的變數怎麼儲存,明天再寫。 以下程式碼中陣列變數被並行寫,引發了錯誤。
#include <iostream> // std::cout #include <future> // std::async, std::future, std::launch #include <ctime> int n = 7; int s[20]={0}; int q(int i, int j, int k, int l) { int ans = 0;; for(int a = ((1 << n) - 1) & ~(i | j | k), p = a & -a; a!=0; a ^= p, p = a & -a) {s[l]=p; ans += q(i | p, (j | p) * 2, (k | p) / 2, l + 1); } if(l==n){ for(int x=0;x<n;x++) printf("%d ",s[x]); printf("\n"); } return l == n ? 1 : ans; } int main(int argc,char*argv[]) { int a=0; int t=clock(); if (argc==2) n=atoi(argv[1]); a=q(0, 0, 0, 0); printf("(normal)result of %d Q is %d,time is %d ms\n", n,a,clock()-t); for(int x=0;x<n;s[x++]=0); a=0; t=clock(); std::future < int >fb[20]; for(int i=0;i<n;i++) fb[i]=std::async(std::launch::async, q,(1<<i),(1<<i)*2,(1<<i)/2,1); for(int i=0;i<n;i++) a+=fb[i].get(); printf("(mthred)result of %d Q is %d,time is %d ms\n",n,a,clock()-t); for(int x=0;x<n;s[x++]=0); a=0; t=clock(); for(int i=0;i<n/2+(n%2);i++) fb[i]=std::async(std::launch::async, q,(1<<i),(1<<i)*2,(1<<i)/2,1); int b=0; if(n%2==1) b=fb[n/2+(n%2)-1].get(); for(int i=0;i<n/2;i++) a+=fb[i].get(); a=2*a+b; printf("(mthred+half)result of %d Q is %d,time is %d ms\n",n,a,clock()-t); for(int x=0;x<n;s[x++]=0); a=0; int fnomp[20]; t=clock(); for(int i=0;i<n/2+(n%2);i++) fnomp[i]=q((1<<i),(1<<i)*2,(1<<i)/2,1); b=0; if(n%2==1) b=fnomp[n/2+(n%2)-1]; for(int i=0;i<n/2;i++) a+=fnomp[i]; a=2*a+b; printf("(no_omp+half)result of %d Q is %d,time is %d ms\n",n,a,clock()-t); for(int x=0;x<n;s[x++]=0); a=0; int fomp[20]; t=clock(); #pragma omp parallel for for(int i=0;i<n/2+(n%2);i++) fomp[i]=q((1<<i),(1<<i)*2,(1<<i)/2,1); b=0; if(n%2==1) b=fomp[n/2+(n%2)-1]; for(int i=0;i<n/2;i++) a+=fomp[i]; a=2*a+b; printf("(omp+half)result of %d Q is %d,time is %d ms\n",n,a,clock()-t); return 0; }
用陣列複製和二維陣列解決了部分問題,遺留了n為奇數計算一半問題。
#include <iostream> // std::cout #include <future> // std::async, std::future, std::launch #include <ctime> #include <cmath> int n = 5; int s[20]={0}; int f=0; void printq(int s[],int n,int f) { for(int x=0;x<n;x++) printf("%.*s\n",n,"------------------Q------------------"+(19-n)+(int)round(log(s[x])/log(2))); printf("\n"); if(f==2) { for(int x=0;x<n;x++) printf("%.*s\n",n,"------------------Q------------------"+(19-n)+(int)round(log((1<<(n-1))/s[x])/log(2))); printf("mirror\n"); } } int q(int s[20],int i, int j, int k, int l) { int ans = 0;; for(int a = ((1 << n) - 1) & ~(i | j | k), p = a & -a; a!=0; a ^= p, p = a & -a){ s[l]=p; ans += q(s,i | p, (j | p) * 2, (k | p) / 2, l + 1); } if(l==n){ for(int x=0;x<n;x++) printf("%d ",s[x]); printf("\n"); } return l == n ? 1 : ans; } int q1(int s[20],int i, int j, int k, int l,int f) { int ans = 0; int s1[20]; //temp array for(int x=0;x<l;x++) s1[x]=s[x]; for(int a = ((1 << n) - 1) & ~(i | j | k), p = a & -a; a!=0; a ^= p, p = a & -a) { s1[l]=p; ans += q1(s1,i | p, (j | p) * 2, (k | p) / 2, l + 1,f); } if(l==n){ printq(s1,n,f); } return l == n ? 1 : ans; } int main(int argc,char*argv[]) { int a=0; int t=clock(); if (argc==2) n=atoi(argv[1]); //method 1 normal a=q1(s,0, 0, 0, 0,1); printf("(normal)result of %d Q is %d,time is %d ms\n", n,a,clock()-t); //method 2 std:thread/async a=0; t=clock(); std::future < int >fb[20]; int s2[20][20]={{0}}; for(int i=0;i<n;i++) { s2[i][0]=1<<i; fb[i]=std::async(std::launch::async, q1,s2[i],(1<<i),(1<<i)*2,(1<<i)/2,1,1); } for(int i=0;i<n;i++) a+=fb[i].get(); printf("(mthred)result of %d Q is %d,time is %d ms\n",n,a,clock()-t); //method 3 std:thread/async compute half a=0; t=clock(); for(int i=0;i<n/2+(n%2);i++) fb[i]=std::async(std::launch::async, q1,s2[i],(1<<i),(1<<i)*2,(1<<i)/2,1,((n%2==1) && (i==n/2))?1:2); int b=0; if(n%2==1) b=fb[n/2+(n%2)-1].get(); for(int i=0;i<n/2;i++) a+=fb[i].get(); a=2*a+b; printf("(mthred+half)result of %d Q is %d,time is %d ms\n",n,a,clock()-t); for(int x=0;x<n;s[x++]=0); a=0; int fnomp[20]; t=clock(); for(int i=0;i<n/2+(n%2);i++){ s[0]=(1<<i); fnomp[i]=q1(s,(1<<i),(1<<i)*2,(1<<i)/2,1,((n%2==1) && (i==n/2))?1:2); } b=0; if(n%2==1) b=fnomp[n/2+(n%2)-1]; for(int i=0;i<n/2;i++) a+=fnomp[i]; a=2*a+b; printf("(no_omp+half)result of %d Q is %d,time is %d ms\n",n,a,clock()-t); for(int x=0;x<n;s[x++]=0); a=0; int fomp[20]; t=clock(); #pragma omp parallel for for(int i=0;i<n/2+(n%2);i++){ s2[i][0]=1<<i; fomp[i]=q1(s2[i],(1<<i),(1<<i)*2,(1<<i)/2,1,((n%2==1) && (i==n/2))?1:2); } b=0; if(n%2==1) b=fomp[n/2+(n%2)-1]; for(int i=0;i<n/2;i++) a+=fomp[i]; a=2*a+b; printf("(omp+half)result of %d Q is %d,time is %d ms\n",n,a,clock()-t); return 0; }
以上程式碼用傳引數f解決了何時列印映象的問題。如果不用引數,用全域性變數,仍存在併發訪問,導致不該映象的(首行棋子在中間格的)也被映象了。 關鍵程式碼如下
//method 3 std:thread/async compute half a=0; t=clock(); for(int i=0;i<n/2+(n%2);i++) fb[i]=std::async(std::launch::async, q1,s2[i],(1<<i),(1<<i)*2,(1<<i)/2,1,((n%2==1) && (i==n/2))?1:2);
最後修改完版本,幾乎所有多執行緒都比單執行緒慢。
D:\>g++ mtqp.cpp -fopenmp D:\>a 12 |find "ms" (normal)result of 12 Q is 14200,time is 610 ms (mthred)result of 12 Q is 14200,time is 820 ms (mthred+half)result of 12 Q is 14200,time is 850 ms (no_omp+half)result of 12 Q is 14200,time is 590 ms (omp+half)result of 12 Q is 14200,time is 790 ms D:\>a 13 |find "ms" (normal)result of 13 Q is 73712,time is 3660 ms (mthred)result of 13 Q is 73712,time is 5070 ms (mthred+half)result of 13 Q is 73712,time is 4990 ms (no_omp+half)result of 13 Q is 73712,time is 3630 ms (omp+half)result of 13 Q is 73712,time is 4820 ms
與不輸出圖形的版本差別巨大
D:\>mtq31 14 (normal)result of 14 Q is 365596,time is 680 ms (mthred)result of 14 Q is 365596,time is 282 ms (mthred+half)result of 14 Q is 365596,time is 132 ms
相關文章
- 逆襲職場,有風變程式設計就夠了程式設計
- 為了寫出好程式,有時需要先寫出爛程式
- 為了寫出好程式,有時候你需要先寫出爛程式
- 選了風變程式設計,才發現Python並不難學程式設計Python
- 一行程式碼完成並行任務行程並行
- CNN實現手寫數字識別並改變引數進行分析CNN
- 我編寫得框架,為什麼在併發數量比較多得時候,就沒有響應了。框架
- 共享經濟火爆正當時,而支付寶早早就心動並行動了並行
- 執行上下文、變數物件、作用域鏈、this,看這篇就夠了!變數物件
- 新工具完成了!!!上班時間只能用指定的部分程式了。唉,有時太過火了~~
- 解決企業採購管理的難題有Ta就夠了
- python多執行緒-共享全域性變數Python執行緒變數
- job中執行帶有引數的procedure 時的寫法
- 很長時間沒有貼文章了,今天沒有什麼事情就寫的關於破解win98屏保密碼的文章,大家共享一下嗎!密碼
- 我已經寫了48年程式碼了,我感覺我還能寫下去
- JavaScript 同時宣告多個變數並賦值JavaScript變數賦值
- 剖析後OpLog訂閱MongoDB的資料變更就沒那麼難了MongoDB
- 面試時寫不出排序演算法?看這篇就夠了。面試排序演算法
- 面試時寫不出排序演算法?看這篇就夠了面試排序演算法
- CTQ難理解?這樣說你就明白了
- Flex很難?一文就足夠了Flex
- C++ 靜態變數什麼時候完成初始化C++變數
- 前端 --弄懂JS的變數提升做這些題就夠了前端JS變數
- Tensorflow學習筆記: 變數及共享變數筆記變數
- 多執行緒中的使用共享變數的問題執行緒變數
- 還重構?就你那程式碼只能鏟了重寫!
- 上傳一個簡單的應用程式並在 4 時間內獲利有多困難?
- Python爬蟲入門並不難,甚至進階也很簡單,掌握了這些就簡單了Python爬蟲
- 在LINUX下編寫程式並執行Linux
- 表變數和臨時表的差別 (以前把表變數叫成變數表了,哎。。。)變數
- 走向並行系列之-使用ForkManager編寫多程式程式並行
- 讀寫分離很難嗎?springboot結合aop簡單就實現了Spring Boot
- linux shell組合多個變數為一個新變數並執行Linux變數
- 想學程式設計並不難 這樣做就可以了程式設計
- 資料分析很難學?60天就夠了!
- 已經有JBUILDER9了??UI
- JS作用域和變數提升看這一篇就夠了JS變數
- 你的程式設計技巧已經過時了嗎?程式設計