如何利用VS的代码优化和openmp并行计算提高程序运行速度

如何利用VS的代码优化和openmp并行计算提高程序运行速度,第1张

以前利用多线程为拥有较大量计算的程序提速过,但也深知多线程的同步和程序的调试是一大坑,最近为实验室的项目学习了一点VS下优化代码的设置以及利用openmp加速运算,都是些很基本的提升程序速度的方法,只要稍微修改下代码和设置,就可使程序加速。配合多线程,经过clock()函数验证,我的程序运行可提高60%的速度,详细如下:

代码优化:

属性->配置属性->C/C++->代码生成:启用增强指令集,可选用 流式处理 SIMD 扩展 2 (/arch:SSE2) (/arch:SSE2)、流式处理 SIMD 扩展 2 (/arch:SSE2) (/arch:SSE2) 进行加速浮点模型,可选用 快速 (/fp:fast) 进行浮点数据运算的加速

属性->配置属性->C/C++->优化:可选用 使速度最大化 (/O2) 进行优化。全程序优化选择是(/GL),在debug版本下不能这样设置,必须在release版本

openmp并行计算:

在vs2012下,项目属性-》C/C++-》语言,openmp支持,选是,包含头文件“omp.h”,对基于数据分集的多线程程序设计,OpenMP是一个很好的选择。

OpenMP常用指令

parallel:用在一个代码段之前,表示这段握键代码将被多个线程并行执行

for:用于for循环之前,将循环分配到多个线程中并行执行,必须保证每次循环之间无相关性

parallel for:parallel 和 for语句的结合,也是用在一个for循环之前,表示for循环的代码将被多个线程并行执行

sections:用在可能会被并行执行的代码段之前

parallel sections:parallel和sections两个语句的结合

critical:用在一段代码临界区之前

single:用在一段只被单个线程执行的代码段之前,表示后面的代码段将被单线程执行

barrier:用于并行区内代码的线程同步,所有线程执行到barrier时要停止,直到所有线程都执行到barrier时才继续册手往下执行

atomic:用于指定一块内存区域被制动更新

master:用于指定一段代码块由主线程执行

ordered:用于指定并行区域的循环按顺序执行

threadprivate:用于指定一个变量是线程私有的

OpenMP除上述指令外,还有一些库函数,下面列出几个常用的库函数:

omp_get_num_procs:返回运行本线程的多处理机的处理器个数

omp_get_num_threads:返回当前并行区域中的活动线程个数

omp_get_thread_num:返回线程号

omp_set_num_threads:设置并行执行代码时的线程个数

omp_init_lock:初始化一个简单锁

omp_set_lock:上锁 *** 作

omp_unset_lock:解锁 *** 作,要和段姿巧omp_set_lock函数配对使用

omp_destroy_lock:omp_init_lock函数的配对 *** 作函数,关闭一个锁

在这里,先回顾一下OpenMP的parallel并行区域线程数量的确定,对于一个并行区域,有一个team的线程去执行,那么该分配多少个线程去执行呢?

OpenMP的遇到parallel指令后创建的线程team的数量由如下过程决定:

1. if子句的结果

2. num_threads的设置

3. omp_set_num_threads()库函数的设置

4. OMP_NUM_THREADS环境变量的设置

5. 编译器默认实现(一般而言,默认实现的是总线程数等于处知宏理器的核心数)

(http://blog.csdn.net/gengshenghong/article/details/6956878查看更多信息)

2、3、4优先级依次降低的,也就是前面的设置可以覆盖后面的设置,当然也是相对而言搭郑册,num_threads子句只会影响当前的并行区域,而omp_set_num_threads对OMP_NUM_THREADS环境变量的覆盖是在整个程序运行期间全局的。

(2)几个容易混淆的OpenMP函数

1. omp_get_thread_num

获取线程的num,即ID。这里的ID是OpenMP的team内的ID,在OpenMP中,一个team内的线程的ID是俺顺序排列的,0、1、2...

说明:此函数在并行区域外或者并行区域内都可以调用。在并行区域外,获取的是master线程的ID,即为0。在并行区域丛旦内,每次执行到此函数,获取的是当前执行线程的ID。

我在TDM-GCC64上把你的程序注释掉“#include "stdafx.h"”之后执行的结果是这样:

这个是链接程序错误,链接程序不识别你的“int ID = omp_get_thread_num()”语句。

这是因为”icl: Command line warning: ignoring option '-Qopenmp'no argument required“,编译器忽略了"-Qopenmp"命令,导致在编译过程中就没有把多线程这一块考虑进去,所以链接不成功。你换个程序试试,还这样的话,查查编译器/命令行为什么忽略"-Qopenmp"命令。

看看这个,可能会有些帮助。

https://software.intel.com/en-us/articles/getting-started-with-openmp/

或者

http://wenku.baidu.com/link?url=yMFQmgRd2E2s7sUuBbET_UJ6CPYIhtw3YqEkgYehMQ1QUq5MKGIMFQTJqu9fJZVvWpqmCjETfzn5uknKTHgAL8iqIR1pcHwoR3GWjhnomPy

如果查不到,那也没办法,因为intel C++ 9.0 貌似是04年的产物,12年了,现在连文档都很难找。它基本只支持32位编程,支持的那点64位平台是IA64而不是amd64,而且,9.0~10.1支持的都是安腾不是酷睿。

所以对于现在的64位平台是amd64,而且架构也发生了巨大改变的CPU,它是否还能发挥它的高效还得两说。而且,我在使用Intel C++ 10.1配合VC6.0时,可以很清楚地看到,它还在调用VC6.0的link库。所以我认为它的效率并不是太高。另:我没有在intel C++ 10.1中安装安腾64这个插件团春,所以不能实现openmp。

对于openmp来讲,我个人不是很推荐初学者使用VS或者VC,微软的那一套东西的确很棒。但那是工作用的东西,搞大工程的话使用多线程会事半功倍;学习的话,还是用学习的工具。学好了再去工作,这不矛盾。

我也很喜欢VC6.0的界面,还有代码换行缩进,如果它一直更新的话我会毫不犹豫地用下去的,毕竟windows平台还是用它自己的东西靠谱。但是它太老了,而且调试太麻烦。

所以,不介意的话,可以用最新版的TDM-GCC64配合C-Free 5.0(跟VC6.0比较像,但是它可以随意更改编译器)。这是个国产的IDE,TDM-GCC64已经内置了openMP,在编译、链接选项卡里加上命令“ -fopenmp"即可。而且调试的时候很方便,它会自动找到与塌败耐你断点有关的所有参数并添加监视。界面也很漂亮,代码缩进也不错(在所有mingw的垃圾IDE中算好的了,可以与codeblocks有一拼)。

另:它可以支持intel C++ compiler 8/9/10/11,我还没有试过,你可以试试。

附图:

可以枯液参看下面的教程:

http://www.ibm.com/developerworks/cn/aix/library/au-aix-openmp-framework/


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/12119976.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存