TL;DR:唯一的区别是第一个代码调用了两个隐式障碍,而第二个代码只调用了一个。
使用现代官方 OpenMP 5.1 标准作为参考的更详细的答案。
这
#pragma omp parallel
:
将创建一个parallel region
包含 的团队threads
,其中每个线程将执行包含的整个代码块parallel region
。
从OpenMP 5.1可以阅读更正式的描述:
当线程遇到并行构造时,会创建一组线程来执行并行区域 (..)。遇到并行构造的线程成为新团队的主线程,在新并行区域的持续时间内线程数为零。新团队中的所有线程,包括主线程,都执行该区域。创建团队后,团队中的线程数在该并行区域的持续时间内保持不变。
这:
#pragma omp parallel for
将创建一个parallel region
(如前所述),并且threads
该区域的 将使用 分配它所包含的循环的迭代default chunk size
,并且通常default schedule
是。但是请记住,标准的不同具体实施可能会有所不同。 static
default schedule
OpenMP
从OpenMP 5.1您可以阅读更正式的描述:
工作共享循环结构指定一个或多个相关循环的迭代将由团队中的线程在其隐式任务的上下文中并行执行。迭代分布在执行工作共享循环区域绑定到的并行区域的团队中已经存在的线程中。
此外,
并行循环构造是指定并行构造的快捷方式,该并行构造包含具有一个或多个关联循环且没有其他语句的循环构造。
或非正式地,#pragma omp parallel for
是构造函数#pragma omp parallel
与#pragma omp for
.
您使用 achunk_size=1
和static schedule
的两个版本都会产生类似的结果:
![在此处输入图像描述](https://i.stack.imgur.com/Vf8AC.png)
在代码方面,循环将被转换为逻辑上类似于:
for(int i=omp_get_thread_num(); i < n; i+=omp_get_num_threads())
{
//...
}
其中omp_get_thread_num()
omp_get_thread_num 例程返回当前团队中调用线程的线程号。
和omp_get_num_threads()
返回当前团队中的线程数。在程序的连续部分中,omp_get_num_threads 返回 1。
或者换句话说,for(int i = THREAD_ID; i < n; i += TOTAL_THREADS)
。THREAD_ID
范围从0
到TOTAL_THREADS - 1
,表示在TOTAL_THREADS
并行区域上创建的团队的线程总数。