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

以前利用多线程为拥有较大量计算的程序提速过,但也深知多线程的同步和程序的调试是一大坑,最近为实验室的项目学习了一点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函数的配对操作函数,关闭一个锁
  • parallel指令用法
#pragma omp parallel num_threads(8)
{
    printf(“Hello, World!, ThreadId=%d\n”, omp_get_thread_num() );
}


 
 
printf函数被创建出的8个线程来执行,每一个线程执行的先后次序并不确定。和传统的创建线程函数比起来,OpenMP相当于为一个线程入口函数重复调用创建线程函数来创建线程并等待线程执行完。如果在上面的代码中去掉num_threads(8)来指定线程数目,那么将根据实际CPU核心数目来创建线程数。
  • for指令用法
#pragma omp parallel for
for ( int j = 0; j < 4; j++ )
{
printf(“Hello, World!, ThreadId=%d\n”, omp_get_thread_num() );
}



 
 
for循环的语句被分配到不同的线程中分开执行了。需要注意的是,如果不添加parallel关键字,那么四次循环将会在同一个线程里执行,必须循环之间无相关性,变量最好都定义在循环内。
  • sections和section的用法
#pragma omp parallel sections
{
#pragma omp section
printf("section 1 ThreadId = %d\n", omp_get_thread_num());
#pragma omp section
printf("section 2 ThreadId = %d\n", omp_get_thread_num());
#pragma omp section
printf("section 3 ThreadId = %d\n", omp_get_thread_num());
#pragma omp section
printf("section 4 ThreadId = %d\n", omp_get_thread_num());
}



 
 
每一个section内部的代码都是(分配到不同的线程中)并行执行的。使用section语句时,需要注意的是这种方式需要保证各个section里的代码执行时间相差不大,否则某个section执行时间比其他section长太多就达不到并行执行的效果了。




你可能感兴趣的:(优化,并行计算,vs,openmp)