OpenMP框架是使用C,C ++和Fortran进行并发编程的强大方法。 GNU编译器集合(GCC)4.2版支持OpenMP 2.5标准,而GCC 4.4支持最新的OpenMP 3标准。 其他编译器,包括Microsoft®Visual Studio,也支持OpenMP。 在本文中,您可以学习使用OpenMP编译器编译指示,查找对OpenMP提供的某些应用程序编程接口(API)的支持,以及使用某些并行算法测试OpenMP。 本文使用GCC 4.2作为首选编译器。
您的第一个OpenMP程序
让我们从一个简单的Hello,World开始! 打印应用程序,其中包含其他实用程序。 清单1显示了代码。
清单1.带OpenMP的Hello World
#include <iostream>
int main()
{
#pragma omp parallel
{
std::cout << "Hello World!\n";
}
}
当使用g ++编译并运行清单1中的代码时,一个Hello,World! 应该显示在控制台中。 现在,使用-fopenmp
选项重新编译代码。 清单2显示了输出。
清单2.使用-fopenmp
命令编译并运行代码
tintin$ g++ test1.cpp -fopenmp
tintin$ ./a.out
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
那么,发生了什么事? 仅当您指定-fopenmp
编译器选项时, #pragma omp parallel
的魔术才-fopenmp
。 在内部,在编译过程中,GCC会根据硬件和操作系统配置生成代码,以在运行时创建尽可能多的最佳线程,每个创建的线程的启动例程都是紧随编译指示之后的块中的代码。 这种行为是隐式并行化,而OpenMP的核心是一组强大的编译指示,使您不必执行大量的样板代码。 (为了进行比较,请检查一下您刚才所做的可移植操作系统接口(POSIX)线程[pthreads]实现是什么样的。)因为我使用的计算机运行的是具有四个物理核心的Intel®Core i7处理器每个物理核心有两个逻辑核心,清单2的输出似乎很合理(8个线程= 8个逻辑核心)。
现在,让我们进入有关并行编译指示的更多详细信息。
OpenMP并行的乐趣
使用pragma的num_threads
参数来控制线程数非常容易。 这又是清单1中的代码,其中指定的可用线程数为5(如清单3所示)。
清单3.用num_threads
控制线程数
#include <iostream>
int main()
{
#pragma omp parallel num_threads(5)
{
std::cout << "Hello World!\n";
}
}
代替num_threads
方法,这是一种更改运行代码的线程数的替代方法。 这也将我们带到您将要使用的第一个OpenMP API: omp_set_num_threads
。 您可以在omp.h标头文件中定义此函数。 无需链接其他库即可使清单4中的代码正常工作-只需-fopenmp
。
清单4.使用omp_set_num_threads
来微调线程的创建
#include <omp.h>
#include <iostream>
int main()
{
omp_set_num_threads(5);
#pragma omp parallel
{
std::cout << "Hello World!\n";
}
}
最后,OpenMP还使用外部环境变量来控制其行为。 您可以调整清单2中的代码以仅打印Hello World! 通过将OMP_NUM_THREADS
变量设置为6
六次。 清单5显示了执行情况。
清单5.使用环境变量来调整OpenMP行为
tintin$ export OMP_NUM_THREADS=6
tintin$ ./a.out
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
您已经发现了OpenMP的所有三个方面:编译器编译指示,运行时API和环境变量。 如果同时使用环境变量和运行时API会发生什么? 运行时API的优先级更高。
一个实际的例子
OpenMP使用隐式并行化技术,您可以使用编译指示,显式函数和环境变量来指示编译器。 让我们看一个示例,其中OpenMP可以提供真正的帮助。 考虑清单6中的代码。
清单6. for
循环中的顺序处理
int main( )
{
int a[1000000], b[1000000];
// ... some initialization code for populating arr