++ 多核cpu 并行_一文读懂什么是多核并行计算(三)
導讀:面向應用工程師的商業軟件咨詢、自研軟件定制開發服務的仿真公眾號,點擊關注進入菜單,查看更多精彩內容。
(三)如何實現多核并行計算呢?
了解了多核、多Machine、多Rack后,我可以看一下軟件(程序)是如何對這些資源進行調度使用的呢?
1、先看看CAE軟件的設置
CAE軟件現在基本上都都號稱是支持多核并行計算的,可以通過界面、求解命令等設置使用的核數,這樣我們拿ansys看一下。
在Ansys中進行并行計算或多核計算設置,可在Ansys的Product Launcher啟動界面的High Performance Computing Setup頁面中進行設置。
在此高級設置頁面中可以設置并行計算多臺多核,也可以設置單臺多核設置,單臺多核可以理解為單CPU多個內核。對于核數設置很多軟件都有個限制,不過據說有些國產CAE軟件是不限制核數的,如果有興趣購買國產CAE軟件的可以聯系本公眾號。言歸正傳咱們看看程序怎么實現的。
2、并行計算簡介
并行平臺的通信模型: 共享數據(POSIX、windows線程、OpenMP)、消息交換(MPI、PVM)。
并行算法模型: 數據并行模型、任務依賴圖模型、工作池模型、管理者-工作者模型、消費者模型對于并行計算一個任務可能涉及到的問題:任務分解、任務依賴關系、任務粒度分配、并發度、任務交互并行算法性能的常見度量值:并行開銷、加速比、效率(加速比/CPU數)、成本(并行運行時間*CPU數)
上面的描述可能不是特別好理解,我們下面通過實例來說明下。
演示中主要完成的工作在Sum0函數(工作本身沒有什么意義,主要是消耗一些時間來代表需要做的工作:),然后分別用OpenMP工具(vc和icc編譯器支持)和一個自己手工寫的線程工具來并行化該函數,來看看多核優化后的效果;我測試用的編譯器是vc2005;CPU是雙核的AMD64x2 4200+(2.37G);內存2G雙通道DDR2 677MHz;(分為三類:純代碼執行、OpenMP并行計算、自己手寫多線程)
3、不用并行的純代碼
#include #include #include #include //一個簡單的耗時任務double Sum0(double* data,long data_count);int main(){long data_count=200000;double* data=new double[data_count];long i;//初始化測試數據for (i=0;idata[i]=(double)(rand()*(1.0/RAND_MAX));const long test_count=200*2;//為了能夠測量出代碼執行的時間,讓函數執行多次double sumresult=0;double runtime=(double)clock();for( i=0; i{sumresult+=Sum0(data,data_count);}runtime=((double)clock()-runtime)/CLOCKS_PER_SEC;printf ("< Sum0 > ");printf (" 最后結果 = %10.4f ",sumresult);printf (" 執行時間(秒) = %f ",runtime);delete [] data;return 0;}double Sum0(double* data,long data_count){double result=0;for (long i=0;i{data[i]=(double)sin(cos(data[i]));result+=data[i];}return result;}看一下輸出結果
< Sum0 >最后結果 = 55590743.4039執行時間(秒) = 6.1560004、使用OpenMP并行計算
OpenMP是基于編譯器命令的并行編程標準,使用的共享數據模型,現在可以用在C/C++、Fortan中;OpenMP命令提供了對并發、同步、數據讀寫的支持;(需要在項目屬性中打開多線程和OpenMP支持,并要在多核CPU上執行才可以看到多CPU并行的優勢)
OpenMP的實現如下:
#include #include #include #include //需要在項目屬性中打開多線程和OpenMP支持#include //用OpenMP實現double Sum_OpenMP(double* data,long data_count);int main(){long data_count=200000;double* data=new double[data_count];long i;//初始化測試數據for (i=0;idata[i]=(double)(rand()*(1.0/RAND_MAX));const long test_count=200*2;//為了能夠測量出代碼執行的時間,讓函數執行多次double sumresult=0;double runtime=(double)clock();for( i=0; i{sumresult+=Sum_OpenMP(data,data_count);}runtime=((double)clock()-runtime)/CLOCKS_PER_SEC;printf ("< Sum_OpenMP > ");printf (" 最后結果 = %10.4f ",sumresult);printf (" 執行時間(秒) = %f ",runtime);delete [] data;return 0;}double Sum_OpenMP(double* data,long data_count){double result=0;#pragma omp parallel for schedule(static) reduction(+: result)for (long i=0;i{data[i]=(double)sin(cos(data[i]));result+=data[i];}return result;}Sum_OpenMP函數相對于Sum0函數只是增加了一句"#pragma omp parallel for schedule(static) reduction(+: result)" ; 它告訴編譯器并行化下面的for循環,并將多個result變量值用+合并;(更多的OpenMP語法請參閱相關資料);
程序運行輸出如下:
< Sum_OpenMP >最后結果 = 55590743.4039執行時間(秒) = 3.0780005、利用多線程來并行化
使用了自定義的CWorkThreadPool多線程工具,此處不貼這部分代碼了。需要在項目屬性中打開多線程支持;多線程并行實現如下:
#include #include #include #include #include #include "WorkThreadPool.h" //使用CWorkThreadPool類double Sum_WorkThreadPool(double* data,long data_count);int main(){long data_count=200000;double* data=new double[data_count];long i;//初始化測試數據for (i=0;idata[i]=(double)(rand()*(1.0/RAND_MAX));const long test_count=200*2;//為了能夠測量出代碼執行的時間,讓函數執行多次double sumresult=0;double runtime=(double)clock();for( i=0; i{sumresult+=Sum_WorkThreadPool(data,data_count);}runtime=((double)clock()-runtime)/CLOCKS_PER_SEC;printf ("< Sum_WorkThreadPool > ");printf (" 最后結果 = %10.4f ",sumresult);printf (" 執行時間(秒) = %f ",runtime);delete [] data;return 0;}double Sum0(double* data,long data_count){double result=0;for (long i=0;i{data[i]=(double)sin(cos(data[i]));result+=data[i];}return result;}struct TWorkData{double* part_data;long part_data_count;double result;};void sum_callback(TWorkData* wd){wd->result=Sum0(wd->part_data,wd->part_data_count);}double Sum_WorkThreadPool(double* data,long data_count){long work_count=CWorkThreadPool::best_work_count();std::vector work_list(work_count);std::vector pwork_list(work_count);long i;//給線程分配任務long part_data_count=data_count/work_count;for (i=0;i{work_list[i].part_data=&data[part_data_count*i];work_list[i].part_data_count=part_data_count;}work_list[work_count-1].part_data_count=data_count-part_data_count*(work_count-1);for (i=0;ipwork_list[i]=&work_list[i];//利用多個線程執行任務 阻塞方式的調用CWorkThreadPool::work_execute((TThreadCallBack)sum_callback,(void**)&pwork_list[0],pwork_list.size());double result=0;for (i=0;iresult+=work_list[i].result;return result;}用多線程來把代碼并行化從而利用多個CPU核的計算能力,這種方式具有比OpenMP更好的靈活性;但容易看出這種方式沒有OpenMP的實現簡便;Sum_WorkThreadPool函數更多的代碼在處理將計算任務分解成多個獨立任務,然后將這些任務交給CWorkThreadPool執行;程序執行輸出如下:
< Sum_WorkThreadPool >最后結果 = 55590743.4039執行時間(秒) = 3.063000總結:通過三天對于多核并行的講解,相信大家一定有了深刻的認識,希望能夠幫助大家更好的理解CAE軟件并行計算原理,更希望大家能夠分享、轉發、再看等方式傳遞我們的信息給更多的朋友,謝謝。
歡迎大家轉發,并點擊下面的“在看”按鈕,邀請更多的朋友一塊討論仿真技術,謝謝!
總結
以上是生活随笔為你收集整理的++ 多核cpu 并行_一文读懂什么是多核并行计算(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 线程执行完之后会释放吗_java多线程并
- 下一篇: 835 由于安全层无法对远程计算机进行身