正确使用内部函数和openmp

时间:2011-11-02 15:16:11

标签: c++ loops openmp

我有一个调用内部函数的for循环:

some variables
for(int i=0; i< 10000000; i++)
    func(variables)

基本上,func获取对某个数组A的引用,并在A [i]中插入值 - 所以我保证 每次调用func实际上都会尝试将值插入A中的不同位置,并且所有其他输入变量保持与for循环之前相同。所以func是线程安全的。

我可以安全地将代码更改为

some variables
#pragma omp parallel for
for(int i=0; i< 10000000; i++)
    func(variables)

根据我对openmp教程的理解,这还不够好 - 因为openmp库不会知道赋予func的变量是真的线程安全的,所以这会产生尝试执行同步放慢速度,我需要声明变量私有等。但实际上,当尝试上面的代码时,它似乎确实更快和并行 - 这是否如预期的那样?我只是想确保我没有错过任何东西。

func声明:

 func(int i, int client_num, const vector<int>& vec)

2 个答案:

答案 0 :(得分:4)

首先,OpenMP无法神奇地确定对代码的依赖性。您的责任是代码对于并行化是正确的。

为了安全地并行化for循环,func必须不具有循环携带流依赖或迭代间依赖性,尤其是对于read-after-write模式。此外,您必须检查没有静态变量。 (实际上,在这个简短的答案中写下安全并行化的条件要复杂得多。)


您对func的说明表明func会将变量写入不同的位置。如果是这样,您可以通过放置pragma omp parallel for来安全地并行化,除非其他计算不依赖于禁止并行化。

func的原型:func(int i, int client_num, const vector<int>& vec)

有一个vector,但它是一个常量,所以vec不应该有任何依赖。从不同线程同时读取是安全的。

但是,你说输出是不同的。这意味着有些事情是错误的。不可能说出问题所在。显示功能原型永远不会有帮助;我们需要知道进行了哪种计算func

尽管如此,诊断的一些步骤是:

  • 检查代码中的依赖关系。你不能有下面所示的依赖。请注意,数组A具有循环携带依赖性,这将阻止并行化:

for (int k = 1; k <N; ++k) A[k] = A[k-1]+1;

  • 检查func是重入或线程安全的。大多数情况下,静态和全局变量可能会破坏您的代码。如果是这样,您可以通过私有化解决此问题。在OpenMP中,您可以在private子句中声明这些变量。此外,OpenMP中有threadprivate个pragma。

答案 1 :(得分:1)

您不会更改循环变量i的任何位置,因此编译器并行化它没有问题。因为我只是复制到你的功能,它不能在外面改变。

您唯一需要确保的是,您只能将函数内部写入位置A [i]并且只能从位置A [i]读取。否则你可能会遇到竞争条件。