一点号申请原创没有通过,机会只有一次你不珍惜申请机会的,还有必要做嘛,一点号?

同时更新资讯所属地
暂无更新,休息一会儿
白羊座(03.21-04.19)
金牛座(04.20-05.20)
双子座(05.21-06.21)
巨蟹座(06.22-07.22)
狮子座(07.23-08.22)
处女座(08.23-09.22)
天秤座(09.23-10.23)
天蝎座(10.24-11.22)
射手座(11.23-12.21)
摩羯座(12.22-01.19)
水瓶座(01.20-02.18)
双鱼座(02.19-03.20)
今日运势:
本日可多参与公众事务,将自己的意见与兴趣结合,提供同好们做参考,让欢乐的气氛添加一些趣味性...您(@)目前可用积分:3512540跟帖回复
共获得打赏:
凯迪微信公众号扫描二维码关注发现信息价值
微信扫一扫
分享此帖文
延伸阅读|最新热帖
[leolaoxiao]
[奇观世界]
[雪耻报仇]
[逆行斋主人]
[z0z1z2z3]
[作家姚鲁工作室]
[笑看你们]
[动静聚散]
有启发就赞赏一下
优秀帖文推荐
| 只看此人
| 不看此人
9:39:15 &&
&&&&感谢有您笔记文章的一路陪伴!如果有可能,您是否可以组织一些线下的分享活动?
| 只看此人
| 不看此人
14:25:04 &&
&&&&深有同感,从来都是行动决定结果,如果再让我重活一次,我一定能成为一个伟人!理论上是的,但结果未必,罗胖的道理我们都知道,问题是谁能有把握说第二次生命就能付诸行动?不怕慢就怕停。不怕万人阻挡,就怕自己投降。新的一年,我决不投降!
| 只看此人
| 不看此人
19:38:29 &&
| 只看此人
| 不看此人
19:47:28 &&
| 只看此人
| 不看此人
9:26:17 &&
| 只看此人
| 不看此人
9:38:33 &&
9:26:17&&的原帖:ok谢谢关注
| 只看此人
| 不看此人
10:33:45 &&
那你讲一点有用的吧。
| 只看此人
| 不看此人
10:46:32 &&
10:33:45&&的原帖:那你讲一点有用的吧。听人讲,永无止境;立刻做,才有出路。
| 只看此人
| 不看此人
11:00:12 &&
那你赶紧做吧。
| 只看此人
| 不看此人
11:07:36 &&
11:00:12&&的原帖:那你赶紧做吧。谢谢,2017的计划按部就班的运行,包括出版和一些事务的运作都是积极有效的,每天做一点,也说不上坚持,而成了乐趣。
| 只看此人
| 不看此人
11:20:10 &&
&&&&只要开始永远不晚!加油吧。
| 只看此人
| 不看此人
11:25:56 &&
11:20:10&&的原帖:&&&&只要开始永远不晚!加油吧。是这个理,谢谢指教
| 只看此人
| 不看此人
12:13:07 &&
创作些漫画、音乐来表现吧,只会写字和磨嘴皮的文科生是无用的。
共 3447 次点击,15 个回复& 1
跳转论坛至:
╋猫论天下&&├猫眼看人&&├商业创富&&├时局深度&&├经济风云&&├文化散论&&├原创评论&&├中间地带&&├以案说法&&├股市泛舟&&├会员阅读&&├舆情观察&&├史海钩沉╋生活资讯&&├杂货讨论&&├健康社会&&├家长里短&&├吃喝玩乐&&├职场生涯&&├咱们女人&&├家有宝宝&&├消费观察&&├房产家居&&├车友评车&&├猫眼鉴宝╋影音娱乐&&├图画人生&&├猫影无忌&&├影视评论&&├音乐之声&&├网友风采&&├娱乐八卦&&├笑话人生&&├游戏天地╋文化广场&&├菁菁校园&&├甜蜜旅程&&├心灵驿站&&├原创文学&&├汉诗随笔&&├闲话国粹&&├体育观察&&├开心科普&&├IT 数码╋地方频道&&├会馆工作讨论区&&├江西会馆&&├凯迪西南&&├海南会馆&&├珠三角&&├凯迪深圳&&├北京会馆&&├上海会馆&&├河南会馆&&├长三角&&├贵州会馆&&├杭州会馆&&├香港会馆&&├台湾会馆&&├美洲会馆╋凯迪重庆╋站务&&├站务专区&&├企业家园&&├十大美帖&&├视频创作&&├商品发布
快速回复:[原创]罗胖讲了那么多,其实一点用都没有!
本站声明:本站BBS互动社区的文章由网友自行帖上,文责自负,对于网友的贴文本站均未主动予以提供、组织或修改;本站对网友所发布未经确证的商业宣传信息、广告信息、要约、要约邀请、承诺以及其他文字表述的真实性、准确性、合法性等不作任何担保和确认。因此本站对于网友发布的信息内容不承担任何责任,网友间的任何交易行为与本站无涉。任何网络媒体或传统媒体如需刊用转帖转载,必须注明来源及其原创作者。特此声明!
【管理员特别提醒】 发布信息时请注意首先阅读 ( 琼B2- ):
;。谢谢!最美的不是下雨天,是曾与你躲过雨的屋檐!
openMP的一点使用经验【非原创】
按照百科上说的,针对于openmp的编程,最简单的就是在开头加个#include&omp.h&,然后在后面的for上加一行#pragma omp parallel for即可,下面的是较为详细的介绍了openmp的入门。
OpenMP:OpenMp是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于并行系统的多线程程序设计的一套指导性的编译处理方案(Compiler
Directive)。
TBB:TBB,Thread Building Blocks,线程构建模块,是公司开发的并行编程开发的工具。
MPI:MPI是一个跨语言的通讯协议,用于编写并行计算机。支持点对点和广播。MPI是一个信息传递应用程序接口,包括协议和和语义说明,他们指明其如何在各种实现中发挥其特性。MPI的目标是高性能,大规模性,和可移植性。MPI在今天仍为高性能计算的主要模型。(可作为扩展阅读!)
下面的是转自博客园http://www.cnblogs.com/yangyangcv/archive//2413335.html。
最近在看多核编程。简单来说,由于现在电脑CPU一般都有两个核,4核与8核的CPU也逐渐走入了寻常百姓家,传统的单线程编程方式难以发挥多核CPU的强大功能,于是多核编程应运而生。按照我的理解,多核编程可以认为是对多线程编程做了一定程度的抽象,提供一些简单的API,使得用户不必花费太多精力来了解多线程的底层知识,从而提高编程效率。这两天关注的多核编程的工具包括openMP和TBB。按照目前网上的讨论,TBB风头要盖过openMP,比如openCV过去是使用openMP的,但从2.3版本开始抛弃openMP,转向TBB。但我试下来,TBB还是比较复杂的,相比之下,openMP则非常容易上手。因为精力和时间有限,没办法花费太多时间去学习TBB,就在这里分享下这两天学到的openMP的一点知识,和大家共同讨论。
openMP支持的编程语言包括C语言、C++和Fortran,支持OpenMP的编译器包括Sun Studio,Intel Compiler,Microsoft Visual Studio,GCC。我使用的是Microsoft Visual Studio 2008,CPU为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遍。
1 #include &iostream& 2 #include &time.h& 3 void test() 4 { 5
int a = 0; 6
for (int i=0;i&;i++) 7
a++; 8 } 9 int main()10 {11
clock_t t1 = clock();12
for (int i=0;i&8;i++)13
clock_t t2 = clock();15
std::cout&&"time: "&&t2-t1&&std::16 }
编译运行后,打印出来的耗时为:1.971秒。下面我们用一句话把上面代码变成多核运行。
1 #include &iostream& 2 #include &time.h& 3 void test() 4 { 5
int a = 0; 6
for (int i=0;i&;i++) 7
a++; 8 } 9 int main()10 {11
clock_t t1 = clock();12
#pragma omp parallel for13
for (int i=0;i&8;i++)14
clock_t t2 = clock();16
std::cout&&"time: "&&t2-t1&&std::17 }
编译运行后,打印出来的耗时为:0.546秒,几乎为上面时间的1/4。
由此我们可以看到openMP的简单易用。在上面的代码里,我们一没有额外include头文件(个人:可以添加#include&omp.h&),二没有额外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核数),然后把每份指派给一个核去执行,而且多核之间为并行执行。下面的代码验证了这种分析。
1 #include &iostream&2 int main()3 {4 #pragma omp parallel for5
for (int i=0;i&10;i++)6
std::cout&&i&&std::7
return 0;8 }
会发现控制台打印出了0 3 4 5 8 9 6 7 1 2。注意:因为每个核之间是并行执行,所以每次执行时打印出的顺序可能都是不一样的。
下面我们来了谈谈竞态条件(race condition)的问题,这是所有多线程编程最棘手的问题。该问题可表述为,当多个线程并行执行时,有可能多个线程同时对某变量进行了读写操作,从而导致不可预知的结果。比如下面的例子,对于包含10个整型元素的数组a,我们用for循环求它各元素之和,并将结果保存在变量sum里。
1 #include &iostream& 2 int main() 3 { 4
int sum = 0; 5
int a[10] = {1,2,3,4,5,6,7,8,9,10}; 6 #pragma omp parallel for 7
for (int i=0;i&10;i++) 8
sum = sum + a[i]; 9
std::cout&&"sum: "&&sum&&std::10
return 0;11 }
如果我们注释掉#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里,代码如下
1 #include &iostream& 2 #include &omp.h& 3 int main(){ 4
int sum = 0; 5
int a[10] = {1,2,3,4,5,6,7,8,9,10}; 6
int coreNum = omp_get_num_procs();//获得处理器个数 7
int* sumArray = new int[coreNum];//对应处理器个数,先生成一个数组 8
for (int i=0;i&coreNi++)//将数组各元素初始化为0 9
sumArray[i] = 0;10 #pragma omp parallel for11
for (int i=0;i&10;i++)12
int k = omp_get_thread_num();//获得每个线程的ID14
sumArray[k] = sumArray[k]+a[i];//对应的将每个线程上的数值独立相加15
for (int i = 0;i&coreNi++)17
sum = sum + sumArray[i];18
std::cout&&"sum: "&&sum&&std::19
return 0;20 }
需要注意的是,在上面代码里,我们用omp_get_num_procs()函数来获取处理器个数,用omp_get_thread_num()函数来获得每个线程的ID,为了使用这两个函数,我们需要include &omp.h&。
上面的代码虽然达到了目的,但它产生了较多的额外操作,比如要先生成数组sumArray,最后还要用一个for循环将它的各元素累加起来,有没有更简便的方式呢?答案是有,openMP为我们提供了另一个工具,归约(reduction),见下面代码:
1 #include &iostream& 2 int main(){ 3
int sum = 0; 4
int a[10] = {1,2,3,4,5,6,7,8,9,10}; 5 #pragma omp parallel for reduction(+:sum) 6
for (int i=0;i&10;i++) 7
sum = sum + a[i]; 8
std::cout&&"sum: "&&sum&&std:: 9
return 0;10 }
上面代码里,我们在#pragma omp parallel for 后面加上了 reduction(+:sum),它的意思是告诉编译器:下面的for循环你要分成多个线程跑,但每个线程都要保存变量sum的拷贝,循环结束后,所有线程把自己的sum累加起来作为最后的输出。
reduction虽然很方便,但它只支持一些基本操作,比如+,-,*,&,|,&&,||等。有些情况下,我们既要避免race condition,但涉及到的操作又超出了reduction的能力范围,应该怎么办呢?这就要用到openMP的另一个工具,critical。来看下面的例子,该例中我们求数组a的最大值,将结果保存在max里。
1 #include &iostream& 2 int main(){ 3
int max = 0; 4
int a[10] = {11,2,33,49,113,20,321,250,689,16}; 5 #pragma omp parallel for 6
for (int i=0;i&10;i++) 7
int temp = a[i]; 9 #pragma omp critical10
if (temp & max)12
std::cout&&"max: "&&max&&std::16
return 0;17 }
上例中,for循环还是被自动分成N份来并行执行,但我们用#pragma omp critical将 if (temp & max) max = temp 括了起来,它的意思是:各个线程还是并行执行for里面的语句,但当你们执行到critical里面时,要注意有没有其他线程正在里面执行,如果有的话,要等其他线程执行完再进去执行。这样就避免了race condition问题,但显而易见,它的执行速度会变低,因为可能存在线程等待的情况。(个人:这个的使用和CUDA中的__syncthreads()栅栏同步函数的功能一样)
有了以上基本知识,对我来说做很多事情都足够了。下面我们来看一个具体的应用例,从硬盘读入两幅图像,对这两幅图像分别提取特征点,特征点匹配,最后将图像与匹配特征点画出来。理解该例子需要一些图像处理的基本知识,我不在此详细介绍。另外,编译该例需要opencv,我用的版本是2.3.1,关于opencv的安装与配置也不在此介绍。我们首先来看传统串行编程的方式。
1 #include "opencv2/highgui/highgui.hpp" 2 #include "opencv2/features2d/features2d.hpp" 3 #include &iostream& 4 #include &omp.h& 5 int main( ){ 6
cv::SurfFeatureDetector detector( 400 );
cv::SurfDescriptorE 8
cv::BruteForceMatcher&cv::L2&float& & 9
std::vector& cv::DMatch &10
cv::Mat im0,im1;11
std::vector&cv::KeyPoint& keypoints0,keypoints1;12
cv::Mat descriptors0, descriptors1;13
double t1 = omp_get_wtime( );14
//先处理第一幅图像15
im0 = cv::imread("rgb0.jpg", CV_LOAD_IMAGE_GRAYSCALE );16
detector.detect( im0, keypoints0);17
extractor.compute( im0,keypoints0,descriptors0);18
std::cout&&"find "&&keypoints0.size()&&"keypoints in im0"&&std::19
//再处理第二幅图像20
im1 = cv::imread("rgb1.jpg", CV_LOAD_IMAGE_GRAYSCALE );21
detector.detect( im1, keypoints1);22
extractor.compute( im1,keypoints1,descriptors1);23
std::cout&&"find "&&keypoints1.size()&&"keypoints in im1"&&std::24
double t2 = omp_get_wtime( );25
std::cout&&"time: "&&t2-t1&&std::26
matcher.match( descriptors0, descriptors1, matches );27
cv::Mat img_28
cv::drawMatches( im0, keypoints0, im1, keypoints1, matches, img_matches ); 29
cv::namedWindow("Matches",CV_WINDOW_AUTOSIZE);30
cv::imshow( "Matches", img_matches );31
cv::waitKey(0);32
return 1;33 }
很明显,读入图像,提取特征点与特征描述子这部分可以改为并行执行,修改如下:
1 #include "opencv2/highgui/highgui.hpp" 2 #include "opencv2/features2d/features2d.hpp" 3 #include &iostream& 4 #include &vector& 5 #include &omp.h& 6 int main( ){ 7
int imNum = 2; 8
std::vector&cv::Mat& imVec(imNum); 9
std::vector&std::vector&cv::KeyPoint&&keypointVec(imNum);10
std::vector&cv::Mat& descriptorsVec(imNum);11
cv::SurfFeatureDetector detector( 400 );
cv::SurfDescriptorE12
cv::BruteForceMatcher&cv::L2&float& &13
std::vector& cv::DMatch &14
char filename[100];//图片路径15
double t1 = omp_get_wtime( );16 #pragma omp parallel for17
for (int i=0;i&imNi++){18
sprintf(filename,"rgb%d.jpg",i);//设置第i个图片的完整名称19
imVec[i] = cv::imread( filename, CV_LOAD_IMAGE_GRAYSCALE );20
detector.detect( imVec[i], keypointVec[i] );21
extractor.compute( imVec[i],keypointVec[i],descriptorsVec[i]);22
std::cout&&"find "&&keypointVec[i].size()&&"keypoints in im"&&i&&std::23
double t2 = omp_get_wtime( );25
std::cout&&"time: "&&t2-t1&&std::26
matcher.match( descriptorsVec[0], descriptorsVec[1], matches );27
cv::Mat img_28
cv::drawMatches( imVec[0], keypointVec[0], imVec[1], keypointVec[1], matches, img_matches ); 29
cv::namedWindow("Matches",CV_WINDOW_AUTOSIZE);30
cv::imshow( "Matches", img_matches );31
cv::waitKey(0);32
return 1;33 }
两种执行方式做比较,时间为:2.343秒v.s. 1.2441秒
在上面代码中,为了改成适合#pragma omp parallel for执行的方式,我们用了STL的vector来分别存放两幅图像、特征点与特征描述子,但在某些情况下,变量可能不适合放在vector里,此时应该怎么办呢?这就要用到openMP的另一个工具,section,代码如下:
1 #include "opencv2/highgui/highgui.hpp" 2 #include "opencv2/features2d/features2d.hpp" 3 #include &iostream& 4 #include &omp.h& 5 int main( ){ 6
cv::SurfFeatureDetector detector( 400 );
cv::SurfDescriptorE 7
cv::BruteForceMatcher&cv::L2&float& & 8
std::vector& cv::DMatch & 9
cv::Mat im0,im1;10
std::vector&cv::KeyPoint& keypoints0,keypoints1;11
cv::Mat descriptors0, descriptors1;12
double t1 = omp_get_wtime( );13 #pragma omp parallel sections14
{15 #pragma omp section16
std::cout&&"processing im0"&&std::18
im0 = cv::imread("rgb0.jpg", CV_LOAD_IMAGE_GRAYSCALE );19
detector.detect( im0, keypoints0);20
extractor.compute( im0,keypoints0,descriptors0);21
std::cout&&"find "&&keypoints0.size()&&"keypoints in im0"&&std::22
}23 #pragma omp section24
std::cout&&"processing im1"&&std::26
im1 = cv::imread("rgb1.jpg", CV_LOAD_IMAGE_GRAYSCALE );27
detector.detect( im1, keypoints1);28
extractor.compute( im1,keypoints1,descriptors1);29
std::cout&&"find "&&keypoints1.size()&&"keypoints in im1"&&std::30
double t2 = omp_get_wtime( );33
std::cout&&"time: "&&t2-t1&&std::34
matcher.match( descriptors0, descriptors1, matches );35
cv::Mat img_36
cv::drawMatches( im0, keypoints0, im1, keypoints1, matches, img_matches ); 37
cv::namedWindow("Matches",CV_WINDOW_AUTOSIZE);38
cv::imshow( "Matches", img_matches );39
cv::waitKey(0);40
return 1;41 }
上面代码中,我们首先用#pragma omp parallel sections将要并行执行的内容括起来,在它里面,用了两个#pragma omp section,每个里面执行了图像读取、特征点与特征描述子提取。将其简化为伪代码形式即为:
1 #pragma omp parallel sections 2 { 3
#pragma omp section 4
function1(); 6
} 7   #pragma omp section 8
function2();10
意思是:parallel sections里面的内容要并行执行,具体分工上,每个线程执行其中的一个section,如果section数大于线程数,那么就等某线程执行完它的section后,再继续执行剩下的section。在时间上,这种方式与人为用vector构造for循环的方式差不多,但无疑该种方式更方便,而且在单核机器上或没有开启openMP的编译器上,该种方式不需任何改动即可正确编译,并按照单核串行方式执行。
以上分享了这两天关于openMP的一点学习体会,其中难免有错误,欢迎指正。另外的一点疑问是,看到各种openMP教程里经常用到private,shared等来修饰变量,这些修饰符的意义和作用我大致明白,但在我上面所有例子中,不加这些修饰符似乎并不影响运行结果,不知道这里面有哪些讲究。
在写上文的过程中,参考了包括以下两个网址在内的多个地方的资源,不再一 一列出,在此一并表示感谢。
http://blog.csdn.net/drzhouweiming/article/details/4093624
http://software.intel.com/zh-cn/articles/more-work-sharing-with-openmp
该博文下面有几个有价值的问题:
[1] 采用clock()计时,并行比串行时间还长。本人试验了别的计时方式,效果还可以。可以参看博文《CentOS6中OpenMP的运行时间或运行性能分析》
OpenMP: OpenMP编程指南
关于利用Openmp中使用的时间函数
openmp并行的计时问题
【亲测】centos7下caffe使用openblas-openmp(多线程版本)多线程加速
OpenMP编程入门之一
openMP编程过程中的一些注意事项
使用OpenMP给程序加速
openmp在多重循环内的简单使用及其详解
OpenMP实现数组并行相加
没有更多推荐了,最新文章 热门文章 热评文章

我要回帖

更多关于 平行志愿只有一次投档机会 的文章

 

随机推荐