OpenMP:如何在每个线程中利用递归函数?
Posted
技术标签:
【中文标题】OpenMP:如何在每个线程中利用递归函数?【英文标题】:OpenMP: How to utilize recursive function in each thread? 【发布时间】:2016-03-24 22:20:09 【问题描述】:#include <stdio.h>
#include<array>
#include<vector>
#include <omp.h>
std::vector<int> pNum;
std::array<int, 4> arr;
int pGen(int);
int main()
pNum.push_back(2);
pNum.push_back(3);
pGen(10);
for (int i = 0; i < pNum.size(); i++)
printf("%d \n", pNum[i]);
printf("top say: %d", pNum.size());
getchar();
int pGen(int ChunkSize)
//
if (pNum.size() == 50) return 0;
int i, k, n, id;
int state = 0;
//
#pragma omp parallel for schedule(dynamic) private(k, n, id) num_threads(4)
for (i = 1; i < pNum.back() * pNum.back(); i++)
//
id = omp_get_thread_num();
n = pNum.back() + i * 2;
for (k = 1; k < pNum.size(); k++)
//
if (n % pNum[k] == 0) break;
if (n / pNum[k] <= pNum[k])
//
#pragma omp critical
//
if (state == 0)
//
state = 1; pNum.push_back(n); printf("id: %d; number: %d \n", id, n); pGen(ChunkSize); break;
if (state == 1) break;
这是我上面的代码。我正在尝试使用 openMP 调度为每个动态、静态和引导找到前 50 个素数。我从动态开始。不知何故,我意识到我必须使用递归函数,因为我不能使用 do - 在并行结构中。
当我调试上面的代码时,控制台立即打开和关闭,我只能看到“id:0, number:5”和一个“error: blablabla(something)”
奇怪的是我从来没有得到 getchar() 并输出我用来存储素数的向量。我认为这是关于递归函数。还有其他理论吗?
编辑:我碰巧发现了错误: this is the error
【问题讨论】:
@HighPerformanceMark,因为 OP 正在使用 Visual Studio(从链接的屏幕截图中可以看出),她/他被 OpenMP 2.0 卡住了,所以没有明确的任务。 是的,我正在使用 VS。有没有关于openMP的详细教程网页。我找不到任何深入而详细的例子。另外,我可以在VS中增加openMP的错误记录和抛出功能吗? 这越来越有趣了。我添加了 omp_set_nested(1);因为我使用嵌套循环,现在只有 thread_0 正确生成 50 个素数并抛出此错误:'Fatal User Error 1002:'#pragma omp barrier'不正确地嵌套在工作共享结构中'......我没有在任何地方使用屏障在代码中。我开始觉得 VS 惹我了。 如果您只寻找 50 个素数,那么 OpenMP 中隐含的线程创建等开销将永远无法恢复!所以你的序列号会更快... 【参考方案1】:我不知道这对您的算法是否重要,但由于您在主循环期间在pNum
向量中添加数字,pNum.back()
将随着迭代而改变。因此,并行循环的边界将在循环本身期间发生变化:for (i = 1; i < pNum.back() * pNum.back(); i++)
OpenMP 不支持此功能。只有在 Canonical Loop Form 中的循环才能与 OpenMP 并行化。该链接详细解释了它,但它归结为您应该在进入循环之前知道并修复边界:
lb 和 b:与 var 的类型兼容的类型的循环不变表达式
因此,您的代码具有未定义的行为。它可能会或可能不会编译,可能会或可能不会运行,并且可以给出任何结果(或者只是重新格式化您的硬盘)。
如果pNum.back()
在迭代中演化并不重要,那么您可以简单地在循环之前对其进行评估,并将此值用作for
语句中的上限。但如果它很重要,那么您将不得不找到另一种方法来并行化您的循环。
最后,附注:此算法使用嵌套并行,但您并没有明确允许这样做,因为嵌套并行默认禁用,只有最外层对 pGen()
的调用会生成 OpenMP 线程。
【讨论】:
以上是关于OpenMP:如何在每个线程中利用递归函数?的主要内容,如果未能解决你的问题,请参考以下文章