我尝试使用OpenMP编写简单的应用程序.不幸的是我有加速问题.在这个应用程序中,我有一个while循环.该循环的主体由一些指令组成,这些指令应该顺序完成,一个循环.我用它#pragma omp parallel for来实现循环并行.这个循环没有太多工作,但经常被调用.
我准备两个版本的for循环,并在1,2和4个核心上运行应用程序.
版本1(for循环中的4次迭代):22秒,23秒,26秒.
版本2(for循环100000次迭代):20秒,10秒,6秒.
正如您所看到的,当for循环没有太多工作时,2和4核心的时间高于1核心.我想原因是#pragma omp parallel for在while循环的每次迭代中创建新线程.所以,我想问你 - 是否有可能创建一次线程(在while循环之前),并确保while循环中的某些作业将按顺序完成?
#include <omp.h>
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main(int argc, char* argv[])
{
double sum = 0;
while (true)
{
// ...
// some work which should be done sequentially
// ...
#pragma omp parallel for num_threads(atoi(argv[1])) reduction(+:sum)
for(int j=0; j<4; ++j) // version 2: for(int j=0; j<100000; ++j)
{
double x = pow(j, 3.0);
x = sqrt(x);
x = sin(x);
x = cos(x);
x = tan(x);
sum += x;
double y = pow(j, 3.0);
y = sqrt(y);
y = sin(y);
y = cos(y);
y = tan(y);
sum += y;
double z = pow(j, 3.0);
z = sqrt(z);
z = sin(z);
z = cos(z);
z = tan(z);
sum += z;
}
if (sum > 100000000)
{
break;
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
大多数OpenMP实现在程序启动时创建许多线程,并在程序的持续时间内保留它们.也就是说,大多数实现在执行期间不会动态创建和销毁线程; 这样做会在严重的线程管理成本下达到性能.这种线程管理方法与OpenMP的常用用例一致并且适用.
当你增加OpenMP线程的数量时,你看到的减速更有可能是在一个循环上用很少的迭代强加并行开销.Hristo的答案涵盖了这一点.
您可以将并行区域移动到while (true)循环外部并使用该single指令使代码的串行部分仅在一个线程中执行.这将消除fork/join模型的开销.OpenMP在迭代次数很少的thight循环中也不是很有用(比如你的版本1).你基本上是测量OpenMP的开销,因为循环内的工作就完成了真快-即使有10万超越函数取小于第二电流代CPU上(在2 GHz,每个FP大约100次instruciton比另外其他的,它会迭代需要~100毫秒).
这就是为什么OpenMP提供了if(condition)可用于有选择地关闭小循环并行化的子句:
#omp parallel for ... if(loopcnt > 10000)
for (i = 0; i < loopcnt; i++)
...
Run Code Online (Sandbox Code Playgroud)
建议使用schedule(static)常规循环(即循环,其中每次迭代需要大约相同的时间来计算).
| 归档时间: |
|
| 查看次数: |
7720 次 |
| 最近记录: |