2024年3月9日发(作者:)
几年之前,CPU的性能还主要取决于CPU的主频,经过超摩尔定律的发展后,没过多长
时间CPU的主频速度就已接近“极限”,使得单单靠提高CPU的主频来提升性能变得非常困
难。
目前,Intel、AMD等CPU生产商都转而采用了多核技术来提升CPU性能,甚至提出了
群核CPU的概念。这意味着,要充分发挥多核CPU的性能,程序就必须采用多线程并发计算
的方式,传统的串行程序将会极大地浪费多核CPU的运算能力!
C++是上世纪80年代诞生的语言,它的前身是同样风靡全球的C语言。一直以来它都以
代码效率卓越著称,进入多核时代后,因为C++标准库没有提供多线程支持,要用C++开发
出充分利用多核CPU的程序将面临很大挑战。
于是,在C++社区出现了不少优秀的库以支持并行编程,如各种跨平台的线程库,Open
MP,Clik++等。另一方面,微软也从Win2K开始不断地加入线程池API(如QueueUserWork
Item),C++09标准也明确地表示要加入多线程的支持。
使用线程库编写并行程序的优点是可以精确调度各个线程,并且可以在所有C++编译器
里使用。不过要充分发挥多核CPU的性能,还要考虑很多因素,主要难点有:
死锁 编写多线程必然会遇到同步问题,如果同步控制出现问题,就可能出现死
锁或脏数据。
线程之间通信 使用何种机制在多个线程之间通信?即要保证通信数据同步又要
保证效率。
负载平衡 分配到每个线程的工作量要尽量平衡,避免一个线程忙一个线程闲的
情形发生。
资源匹配 程序应该使用多少个线程?过少的线程不能充分利用CPU的多核优
势,而过多的线程会造成线程调度过于频繁同样会降低效率。
OpenMP是目前比较流行的C++并行编程方式,它通过在代码中插入专用的pragma编译
指令来指示编译器把串行代码编译成并行程序。
它的优点是易于使用,几乎不用修改原代码就可对老程序进行并发支持的改造。问题
是它必须要有编译器的支持,尽管目前不少编译器都提供了OpenMP的支 持,但它毕竟不
是C++的一部分,甚至它都不是真正意义上的C++库。。
现在,我们又有了一个新选择:Intel Thread Building Blocks(TBB,线程构建模块)。
TBB是一个开源的C++模板库,能够运行在 Windows、Linux、Macintosh以及UNIX等系统
上,只要是标准的C++编译器都可以使用它。
以下是程序测试的实验案例和测试结果:
for ( int j = 0; j < num; j++ )
{
k[j]=j;
for(int p=0;p<10000;p++)cout(p); //进行很大的for循环,又调用函数,主要
目的就是让它耗时间;
}
for(int i=0;i printf("%d ",k[i]); 很显然,这是一个经典的单线程程序,其中的for(int p=0;p<10000;p++)cout(p); 是 一个内嵌了提高程序复杂性的函数的大循环,主要是为了提高程序的额外开销,以便于我们 能够明显的观察到多线程程序与单线程程序之间的性能差异。整个for程序执行的流程如下 所示: j=0 -> k[j]=j -> 进行复杂运算 -> j!=j++并继续下一个循环num-1?:退出循环 并顺序显示k[num]中的内容 有一点需要注意的是,由于单线程的程序是顺序执行的,所以上面这个程序第二个for 语句其实是可以不必使用的,可以将它内嵌入第一个for语句中: for ( int j = 0; j < num; j++ ) { k[j]=j; for(int p=0;p<10000;p++)cout(p); //进行很大的for循环,又调用函数,主要 目的就是让它耗时间; printf("%d ",k[i]); } 这样可以减少程序额外开销,但是对于多线程程序来说,这点开销是必须的,如果输出 必须是顺序的话,那我们有必要控制它的输出顺序,否则将会出现乱序输出--尽管结果是正 确的,但是输出的顺序却是我们不想看到的。当然,第二个for语句所增加的开销,远远比 不上并行程序运行时所节约的开销。我们使用Intel的openmp技术来创建多线程的程序, 因为openmp技术够直观,也很容易去分析与理解,所以我们无需去调用底层API就能够轻 易的实现多线程编程。要使用openmp技术就要安装Intel编译器及下面的openmp组件, Intel编译器可以很好的与Visual Stdio整合在一起,起码要求是你的计算机上必须安装 了Visual C++6.0。当然,安装完之后我们必须进行一些设置,以Visual Stdio 2008为例, 如果我们想要使用openmp技术的话,我们须在VC项目下右边的“资源管理器”中点“属 性”--“C/C++”--“语言”--有个“openmp支持”选项,选“是(/openmp)”即可。另 外我们必须在程序中插入 做完了最基本的设置之后,我们就可以开始改程序了: #pragma omp parallel for //就多了这么一句,在我的电脑上就快了75%; for ( int j = 0; j < num; j++ ) { k[j]=j; for(int p=0;p<10000;p++)cout(p); }


发布评论