有共享變數時,並行程式就難寫了(已完成)
在前次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
- python多執行緒-共享全域性變數Python執行緒變數
- 執行上下文、變數物件、作用域鏈、this,看這篇就夠了!變數物件
- AI大模型時代,人才的需求已經變了AI大模型
- 解決企業採購管理的難題有Ta就夠了
- 輕流完成數千萬元A輪融資 無程式碼開發時代來了?
- 剖析後OpLog訂閱MongoDB的資料變更就沒那麼難了MongoDB
- JavaScript 同時宣告多個變數並賦值JavaScript變數賦值
- Tensorflow學習筆記: 變數及共享變數筆記變數
- 讀寫分離很難嗎?springboot結合aop簡單就實現了Spring Boot
- 12C開始oracle實現了SCALABLE LGWR多程式並行寫redo logOracle並行
- 還重構?就你那程式碼只能鏟了重寫!
- Python爬蟲入門並不難,甚至進階也很簡單,掌握了這些就簡單了Python爬蟲
- C++ 靜態變數什麼時候完成初始化C++變數
- 前端 --弄懂JS的變數提升做這些題就夠了前端JS變數
- Flex很難?一文就足夠了Flex
- CTQ難理解?這樣說你就明白了
- 上傳一個簡單的應用程式並在 4 時間內獲利有多困難?
- 面試時寫不出排序演算法?看這篇就夠了。面試排序演算法
- 面試時寫不出排序演算法?看這篇就夠了面試排序演算法
- 什麼!程式設計師不乖乖寫程式碼,跑去寫小說了?一時興起寫了《雪中悍刀行》的番外,請品鑑!程式設計師
- Kubernetes 已經成為雲原生時代的安卓,這就夠了嗎?安卓
- 你知道嗎?推行精益生產並不難,難就難在老闆是不是真想幹
- JS作用域和變數提升看這一篇就夠了JS變數
- XUnit資料共享與並行測試並行
- lcobucci/jwt的安裝和使用(讓天下沒有難寫和難讀的程式碼)JWT
- TensorFlow——共享變數的使用方法變數
- 如何在檢視中共享變數變數
- 共享變數、廣播變數,累計器的工作原理圖。變數
- 資料分析很難學?60天就夠了!
- Soso 的並查集寫掛了並查集
- 改變勸酒文化就靠你了
- 微信小程式執行流程看這篇就夠了微信小程式
- 風變程式設計:提升工作效率,短時間完成更多事情程式設計
- 大資料並沒有死,可能是你已經不認識它了大資料
- 大資料並沒有死,只不過你已經不認識它了大資料
- 寫了個全域性變數的bug,被同事們打臉!!!變數