当前位置: 首页 > news >正文

织梦网站系统网站顶部伸缩广告

织梦网站系统,网站顶部伸缩广告,网站如何做360优化,ui设计的定义最近在看多核编程。简单来说#xff0c;由于现在电脑CPU一般都有两个核#xff0c;4核与8核的CPU也逐渐走入了寻常百姓家#xff0c;传统的单线程编程方式难以发挥多核 CPU的强大功能#xff0c;于是多核编程应运而生。按照我的理解#xff0c;多核编程可以认为是对多线程…      最近在看多核编程。简单来说由于现在电脑CPU一般都有两个核4核与8核的CPU也逐渐走入了寻常百姓家传统的单线程编程方式难以发挥多核 CPU的强大功能于是多核编程应运而生。按照我的理解多核编程可以认为是对多线程编程做了一定程度的抽象提供一些简单的API使得用户不必花费太多精力来了解多线程的底层知识从而提高编程效率。这两天关注的多核编程的工具包括openMP和TBB。按照目前网上的讨论TBB风头要盖过 openMP比如openCV过去是使用openMP的但从2.3版本开始抛弃openMP转向TBB。但我试下来TBB还是比较复杂的相比之下openMP则非常容易上手。因为精力和时间有限没办法花费太多时间去学习TBB就在这里分享下这两天学到的openMP的一点知识首先从openMP的基本知识入手最后针对图像特征点提取给出一个结合openCV的具体的例子。openMP支持的编程语言包括C语言、C和Fortran支持OpenMP的编译器包括Sun StudioIntel CompilerMicrosoft Visual StudioGCC。我使用的是Microsoft Visual Studio 2008CPU为Intel i5 四核首先讲一下在Microsoft Visual Studio 2008上openMP的配置。非常简单总共分2步(1) 新建一个工程。这个不再多讲。(2) 建立工程后点击 菜单栏-Project-Properties弹出菜单里点击 Configuration Properties-C/C-Language-OpenMP Support在下拉菜单里选择Yes。至此配置结束。下面我们通过一个小例子来说明openMP的易用性。这个例子是 有一个简单的test()函数然后在main()里用一个for循环把这个test()函数跑8遍。 #include iostream #include time.h void test() {int a 0;for (int i0;i100000000;i)a; } int main() {clock_t t1 clock();for (int i0;i8;i)test();clock_t t2 clock();std::couttime: t2-t1std::endl; } 编译运行后打印出来的耗时为1.971秒。下面我们用一句话把上面代码变成多核运行。 #include iostream #include time.h void test() {int a 0;for (int i0;i100000000;i)a; } int main() {clock_t t1 clock();#pragma omp parallel forfor (int i0;i8;i)test();clock_t t2 clock();std::couttime: t2-t1std::endl; } 编译运行后打印出来的耗时为0.546秒几乎为上面时间的1/4。由此我们可以看到openMP的简单易用。在上面的代码里我们一没有额外include头文件二没有额外link库文件只是在for循环前加了一句#pragma omp parallel for。而且这段代码在单核机器上或者编译器没有将openMP设为Yes的机器上编译也不会报错将自动忽略#pragma这行代码然后按照传统单核串行的方式编译运行我们唯一要多做的一步是从C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.OPENMP和C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86\Microsoft.VC90.DebugOpenMP目录下分别拷贝 vcomp90d.dll和vcomp90.dll文件到工程文件当前目录下。对上面代码按照我的理解做个简单的剖析。当编译器发现#pragma omp parallel for后自动将下面的for循环分成N份(N为电脑CPU核数)然后把每份指派给一个核去执行而且多核之间为并行执行。下面的代码验证了这种分析。 #include iostream int main() { #pragma omp parallel forfor (int i0;i10;i)std::coutistd::endl;return 0; } 会发现控制台打印出了0 3 4 5 8 9 6 7 1 2。注意因为每个核之间是并行执行所以每次执行时打印出的顺序可能都是不一样的。下面我们来了谈谈竞态条件(race condition)的问题这是所有多线程编程最棘手的问题。该问题可表述为当多个线程并行执行时有可能多个线程同时对某变量进行了读写操作从而导致不可预知的结果。比如下面的例子对于包含10个整型元素的数组a我们用for循环求它各元素之和并将结果保存在变量sum里。 #include iostream int main() {int sum 0;int a[10] {1,2,3,4,5,6,7,8,9,10}; #pragma omp parallel forfor (int i0;i10;i)sum sum a[i];std::coutsum: sumstd::endl;return 0; } 如果我们注释掉#pragma omp parallel for让程序先按照传统串行的方式执行很明显sum 55。但按照并行方式执行后sum则会变成其他值比如在某次运行过程中sum 49。其原因是当某线程A执行sum sum a[i]的同时另一线程B正好在更新sum而此时A还在用旧的sum做累加于是出现了错误。那么用openMP怎么实现并行数组求和呢下面我们先给出一个基本的解决方案。该方案的思想是首先生成一个数组sumArray其长度为并行执行的线程的个数(默认情况下该个数等于CPU的核数)在for循环里让各个线程更新自己线程对应的sumArray里的元素最后再将 sumArray里的元素累加到sum里代码如下 #include iostream #include omp.h int main(){int sum 0;int a[10] {1,2,3,4,5,6,7,8,9,10};int coreNum omp_get_num_procs();//获得处理器个数int* sumArray new int[coreNum];//对应处理器个数先生成一个数组for (int i0;icoreNum;i)//将数组各元素初始化为0sumArray[i] 0; #pragma omp parallel forfor (int i0;i10;i){int k omp_get_thread_num();//获得每个线程的IDsumArray[k] sumArray[k]a[i];}for (int i 0;icoreNum;i)sum sum sumArray[i];std::coutsum: sumstd::endl;return 0; } 需要注意的是在上面代码里我们用omp_get_num_procs()函数来获取处理器个数用omp_get_thread_num()函数来获得每个线程的ID为了使用这两个函数我们需要include omp.h。上面的代码虽然达到了目的但它产生了较多的额外操作比如要先生成数组sumArray最后还要用一个for循环将它的各元素累加起来有没有更简便的方式呢答案是有openMP为我们提供了另一个工具归约(reduction)见下面代码 #include iostream int main(){int sum 0;int a[10] {1,2,3,4,5,6,7,8,9,10}; #pragma omp parallel for reduction(:sum)for (int i0;i10;i)sum sum a[i];std::coutsum: sumstd::endl;return 0; } 上面代码里我们在#pragma omp parallel for 后面加上了 reduction(:sum)它的意思是告诉编译器下面的for循环你要分成多个线程跑但每个线程都要保存变量sum的拷贝循环结束后所有线程把自己的sum累加起来作为最后的输出。reduction虽然很方便但它只支持一些基本操作比如,-,*,,|,,||等。有些情况下我们既要避免race condition但涉及到的操作又超出了reduction的能力范围应该怎么办呢这就要用到openMP的另一个工具critical。来看下面的例子该例中我们求数组a的最大值将结果保存在max里。 #include iostream int main(){int max 0;int a[10] {11,2,33,49,113,20,321,250,689,16}; #pragma omp parallel forfor (int i0;i10;i){int temp a[i]; #pragma omp critical{if (temp max)max temp;}}std::coutmax: maxstd::endl;return 0; } 上例中for循环还是被自动分成N份来并行执行但我们用#pragma omp critical将 if (temp max) max temp 括了起来它的意思是各个线程还是并行执行for里面的语句但当你们执行到critical里面时要注意有没有其他线程正在里面执行如果有的话要等其他线程执行完再进去执行。这样就避免了race condition问题但显而易见它的执行速度会变低因为可能存在线程等待的情况。有了以上基本知识对我来说做很多事情都足够了。下面我们来看一个具体的应用例从硬盘读入两幅图像对这两幅图像分别提取特征点特征点匹配最后将图像与匹配特征点画出来。编译该例需要opencv我用的版本是2.3.1关于 opencv的安装与配置不在此介绍。我们首先来看传统串行编程的方式。 #include opencv2/highgui/highgui.hpp #include opencv2/features2d/features2d.hpp #include iostream #include omp.h int main( ){cv::SurfFeatureDetector detector( 400 ); cv::SurfDescriptorExtractor extractor;cv::BruteForceMatchercv::L2float matcher;std::vector cv::DMatch matches;cv::Mat im0,im1;std::vectorcv::KeyPoint keypoints0,keypoints1;cv::Mat descriptors0, descriptors1;double t1 omp_get_wtime( );//先处理第一幅图像im0 cv::imread(rgb0.jpg, CV_LOAD_IMAGE_GRAYSCALE );detector.detect( im0, keypoints0);extractor.compute( im0,keypoints0,descriptors0);std::coutfind keypoints0.size()keypoints in im0std::endl;//再处理第二幅图像im1 cv::imread(rgb1.jpg, CV_LOAD_IMAGE_GRAYSCALE );detector.detect( im1, keypoints1);extractor.compute( im1,keypoints1,descriptors1);std::coutfind keypoints1.size()keypoints in im1std::endl;double t2 omp_get_wtime( );std::couttime: t2-t1std::endl;matcher.match( descriptors0, descriptors1, matches );cv::Mat img_matches;cv::drawMatches( im0, keypoints0, im1, keypoints1, matches, img_matches ); cv::namedWindow(Matches,CV_WINDOW_AUTOSIZE);cv::imshow( Matches, img_matches );cv::waitKey(0);return 1; } 很明显读入图像提取特征点与特征描述子这部分可以改为并行执行修改如下 #include opencv2/highgui/highgui.hpp #include opencv2/features2d/features2d.hpp #include iostream #include vector #include omp.h int main( ){int imNum 2;std::vectorcv::Mat imVec(imNum);std::vectorstd::vectorcv::KeyPointkeypointVec(imNum);std::vectorcv::Mat descriptorsVec(imNum);cv::SurfFeatureDetector detector( 400 ); cv::SurfDescriptorExtractor extractor;cv::BruteForceMatchercv::L2float matcher;std::vector cv::DMatch matches;char filename[100];double t1 omp_get_wtime( ); #pragma omp parallel forfor (int i0;iimNum;i){sprintf(filename,rgb%d.jpg,i);imVec[i] cv::imread( filename, CV_LOAD_IMAGE_GRAYSCALE );detector.detect( imVec[i], keypointVec[i] );extractor.compute( imVec[i],keypointVec[i],descriptorsVec[i]);std::coutfind keypointVec[i].size()keypoints in imistd::endl;}double t2 omp_get_wtime( );std::couttime: t2-t1std::endl;matcher.match( descriptorsVec[0], descriptorsVec[1], matches );cv::Mat img_matches;cv::drawMatches( imVec[0], keypointVec[0], imVec[1], keypointVec[1], matches, img_matches ); cv::namedWindow(Matches,CV_WINDOW_AUTOSIZE);cv::imshow( Matches, img_matches );cv::waitKey(0);return 1; } 两种执行方式做比较时间为2.343秒v.s. 1.2441秒在上面代码中为了改成适合#pragma omp parallel for执行的方式我们用了STL的vector来分别存放两幅图像、特征点与特征描述子但在某些情况下变量可能不适合放在vector里此时应该怎么办呢这就要用到openMP的另一个工具section代码如下 #include opencv2/highgui/highgui.hpp #include opencv2/features2d/features2d.hpp #include iostream #include omp.h int main( ){cv::SurfFeatureDetector detector( 400 ); cv::SurfDescriptorExtractor extractor;cv::BruteForceMatchercv::L2float matcher;std::vector cv::DMatch matches;cv::Mat im0,im1;std::vectorcv::KeyPoint keypoints0,keypoints1;cv::Mat descriptors0, descriptors1;double t1 omp_get_wtime( ); #pragma omp parallel sections{ #pragma omp section{std::coutprocessing im0std::endl;im0 cv::imread(rgb0.jpg, CV_LOAD_IMAGE_GRAYSCALE );detector.detect( im0, keypoints0);extractor.compute( im0,keypoints0,descriptors0);std::coutfind keypoints0.size()keypoints in im0std::endl;} #pragma omp section{std::coutprocessing im1std::endl;im1 cv::imread(rgb1.jpg, CV_LOAD_IMAGE_GRAYSCALE );detector.detect( im1, keypoints1);extractor.compute( im1,keypoints1,descriptors1);std::coutfind keypoints1.size()keypoints in im1std::endl;}}double t2 omp_get_wtime( );std::couttime: t2-t1std::endl;matcher.match( descriptors0, descriptors1, matches );cv::Mat img_matches;cv::drawMatches( im0, keypoints0, im1, keypoints1, matches, img_matches ); cv::namedWindow(Matches,CV_WINDOW_AUTOSIZE);cv::imshow( Matches, img_matches );cv::waitKey(0);return 1; } 上面代码中我们首先用#pragma omp parallel sections将要并行执行的内容括起来在它里面用了两个#pragma omp section每个里面执行了图像读取、特征点与特征描述子提取。将其简化为伪代码形式即为 #pragma omp parallel sections {#pragma omp section{function1();}#pragma omp section{function2();} } 意思是parallel sections里面的内容要并行执行具体分工上每个线程执行其中的一个section如果section数大于线程数那么就等某线程执行完它的 section后再继续执行剩下的section。在时间上这种方式与人为用vector构造for循环的方式差不多但无疑该种方式更方便而且在单核机器上或没有开启openMP的编译器上该种方式不需任何改动即可正确编译并按照单核串行方式执行。以上分享了这两天关于openMP的一点学习体会其中难免有错误欢迎指正。另外的一点疑问是看到各种openMP教程里经常用到 private,shared等来修饰变量这些修饰符的意义和作用我大致明白但在我上面所有例子中不加这些修饰符似乎并不影响运行结果不知道这里面有哪些讲究。在写上文的过程中参考了包括以下两个网址在内的多个地方的资源不再一 一列出在此一并表示感谢。http://blog.csdn.net/drzhouweiming/arti ... ls/4093624http://software.intel.com/zh-cn/article ... ith-openmp原文发表于我的博客http://www.cnblogs.com/yangyangcv/archive/2012/03/23/2413335.html欢迎访问~~转载于:https://www.cnblogs.com/CVArt/archive/2012/06/01/2529824.html
http://www.zqtcl.cn/news/358305/

相关文章:

  • 汉语网站建设心得专业网站的定义
  • 泉州台商区建设局网站论坛内网站怎么建设
  • 做文字云的网站平面设计发展前景
  • 域名注册后怎么建网站万网建站教程
  • 郑州网站建设幸巴石家庄站规模
  • 江华网站建设企业传统的网络营销推广方法
  • 网站开发与推广新网站开发工作总结
  • 永修县建设局网站长沙网站关键词优化
  • 厦门建站服务低代码开发会废了程序员吗
  • 安阳汤阴县网站建设下载wix做的网站
  • 福清市建设局网站深圳工业设计协会封昌红
  • 网站建设公司做网站要多少费用重庆找工作哪个网站好
  • 苏州网站建设方法cnzz网站排名是怎么做的
  • 烟台网站建设服务专业的企业智能建站制造厂家
  • 网站信息查询制作闹钟网站
  • 永久免费个人网站申请注册禁止 wordpress ajax
  • 建设网站江西一个简单的游戏网站建设
  • 织梦大气婚纱影楼网站源码优化大师电脑版
  • 衡水企业网站制作报价怎么通过局域网建设网站
  • 服装网站建设课程知道ip怎么查域名
  • 上海政务网站建设上行10m企业光纤做网站
  • 杭州做公司网站aso搜索优化
  • 南京越城建设集团网站网站空间续费多少钱
  • 深圳nft网站开发公司如何制作微信公众号里的小程序
  • 做网站美工要学什么聊城网站建设电话
  • 南通个人网站建设快手秒刷自助网站
  • html5 做网站网站开发找工作
  • 聚成网站建设艺术公司网站定制中心
  • 阿里云上可以做网站吗十六局集团门户网
  • 门户网站建设询价函有哪些网站可以做设计挣钱