这两者有什么区别?
[一个]
#pragma omp parallel
{
#pragma omp for
for(int i = 1; i < 100; ++i)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
[B]
#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
...
}
Run Code Online (Sandbox Code Playgroud)
Ade*_*ler 61
我认为没有任何区别,一个是另一个的捷径.虽然您的确切实施可能会以不同方式处理它们
组合的并行工作共享构造是用于指定包含一个工作共享构造而不包含其他语句的并行构造的快捷方式.允许的条款是并行和工作共享结构允许的条款的并集.
摘自http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf
OpenMP的规范如下:
https://openmp.org/specifications/
Krz*_*ski 60
这些是等价的.
#pragma omp parallel产生一组线程,同时#pragma omp for在产生的线程之间划分循环迭代.您可以使用fusion #pragma omp parallel for指令同时执行这两项操作.
Nts*_*sDK 26
以下是使用分隔符parallel和for 此处的示例.简而言之,它可以for在多个线程中执行循环之前用于动态分配OpenMP线程专用数组.在以下parallel for情况下进行相同的初始化是不可能的.
UPD:在问题示例中,单个pragma和两个pragma之间没有区别.但实际上,您可以使用分离的parallel和for指令来创建更多线程感知行为.一些代码例如:
#pragma omp parallel
{
double *data = (double*)malloc(...); // this data is thread private
#pragma omp for
for(1...100) // first parallelized cycle
{
}
#pragma omp single
{} // make some single thread processing
#pragma omp for // second parallelized cycle
for(1...100)
{
}
#pragma omp single
{} // make some single thread processing again
free(data); // free thread private data
}
Run Code Online (Sandbox Code Playgroud)
TL;DR:唯一的区别是第一个代码调用2 个隐式屏障,而第二个代码仅调用 1 个。
使用现代官方 OpenMP 5.1 标准作为参考的更详细答案。
OpenMP 条款:
#pragma omp parallel
Run Code Online (Sandbox Code Playgroud)
创建一个parallel region由 组成的团队,其中每个线程将执行并行区域threads的整个代码块。
从OpenMP 5.1中可以读到更正式的描述:
当线程遇到并行构造时,会创建一组线程来执行并行区域 (..)。遇到并行构造的线程成为新团队的主线程,在新并行区域的持续时间内线程数为零。新团队中的所有线程(包括主线程)都会执行该区域。创建团队后,团队中的线程数在该并行区域的持续时间内保持不变。
这:
#pragma omp parallel for
Run Code Online (Sandbox Code Playgroud)
创建一个并行区域(如前所述),并且将使用默认值和(通常为)threads将其包含的循环的迭代分配给该区域。但请记住,这些默认值可能因不同的具体实现而异。chunk sizeschedule staticOpenMP标准的不同具体实现而异。
从OpenMP 5.1中您可以阅读更正式的描述:
工作共享循环构造指定一个或多个关联循环的迭代将由团队中的线程在其隐式任务的上下文中并行执行。迭代分布在团队中已存在的线程中,该团队正在执行工作共享循环区域绑定到的并行区域。
而且,
并行循环构造是一种指定并行构造的快捷方式,该并行构造包含具有一个或多个关联循环且没有其他语句的循环构造。
或者非正式地,#pragma omp parallel for是构造函数#pragma omp parallel与#pragma omp for。
对于您所展示的两个版本,如果使用静态chunk_size=1, 执行流程将导致类似以下结果: schedule
从代码角度来看,循环将转换为逻辑上类似于以下内容的内容:
for(int i=omp_get_thread_num(); i < n; i+=omp_get_num_threads())
{
//...
}
Run Code Online (Sandbox Code Playgroud)
omp_get_thread_num 例程返回当前组内调用线程的线程号。
返回当前组中的线程数。在程序的连续部分中,omp_get_num_threads 返回 1。
或者换句话说,for(int i = THREAD_ID; i < n; i += TOTAL_THREADS). 范围THREAD_ID从0到TOTAL_THREADS - 1,TOTAL_THREADS代表在并行区域上创建的团队线程总数。
虽然具体示例的两个版本都是等效的,但正如其他答案中已经提到的那样,它们之间仍然存在一个小的差异.第一个版本包含一个不必要的隐含障碍,在"omp for"结束时遇到.可以在并行区域的末尾找到另一个隐式屏障.将"nowait"添加到"omp for"将使两个代码等效,至少从OpenMP角度来看.我提到这一点是因为OpenMP编译器可能会为这两种情况生成略有不同的代码.
显然有很多答案,但是这个答案非常好(有来源)
#pragma omp for只为当前团队中的不同线程委派循环的一部分。团队是执行程序的线程组。在程序启动时,团队仅由一个 成员组成:运行程序的主线程。要创建新的线程组,您需要指定 parallel 关键字。它可以在周围的上下文中指定:
Run Code Online (Sandbox Code Playgroud)#pragma omp parallel { #pragma omp for for(int n = 0; n < 10; ++n) printf(" %d", n); }
和:
什么是:并行,为和一个团队
parallel、parallel for 和 for 的区别如下:
团队是当前执行的线程组。在程序开始时,团队由一个线程组成。并行构造在下一个块/语句的持续时间内将当前线程拆分为一个新的线程组,之后该组又合并为一个。for 在当前团队的线程之间分配 for 循环的工作。
它不创建线程,它只在当前执行团队的线程之间分配工作。parallel for 是同时表示两个命令的简写:parallel 和 for。Parallel 创建一个新团队,并拆分该团队以处理循环的不同部分。如果您的程序从不包含并行结构,那么线程永远不会超过一个;启动程序并运行它的主线程,就像在非线程程序中一样。
https://bisqwit.iki.fi/story/howto/openmp/
小智 5
当我在g ++ 4.7.0中使用for循环并使用时,我看到了截然不同的运行时
std::vector<double> x;
std::vector<double> y;
std::vector<double> prod;
for (int i = 0; i < 5000000; i++)
{
double r1 = ((double)rand() / double(RAND_MAX)) * 5;
double r2 = ((double)rand() / double(RAND_MAX)) * 5;
x.push_back(r1);
y.push_back(r2);
}
int sz = x.size();
#pragma omp parallel for
for (int i = 0; i< sz; i++)
prod[i] = x[i] * y[i];
Run Code Online (Sandbox Code Playgroud)
串行代码(否openmp)在79毫秒内运行."并行"代码在29毫秒内运行.如果我省略for并使用#pragma omp parallel,运行时最长可拍摄179ms,这比串行代码慢.(该机器的并发性为8)
代码链接到 libgomp
| 归档时间: |
|
| 查看次数: |
155353 次 |
| 最近记录: |