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