我在调用自己的函数时遇到麻烦 在这种情况下,我不清楚使用openmp进行线程化的正确方法。
code
我这样做的方式,它运行多个线程并且是正确的,但似乎没有没有openmp支持的速度更快。
有办法解决吗?还是因为代码的方式而变得无助。
答案 0 :(得分:1)
据我所理解的代码,总体目标实质上是生成所有可以由N
个字母组成的length
个字母的单词。对gen()
的每个递归调用都对应一个字母位置,因此,每次控件到达递归的底部时,N
的前arrayofindex
个元素就代表一个单词的字母。>
但是很明显,并行运行的多个线程不能使用相同的arrayofindex
。每个线程都希望到达递归的底部时,在arrayofindex
中查找沿其递归路径设置的 值。这是该方法的基础。如果其他线程同时修改arrayofindex
,则它们都可能混入不同线程设置的值。而且,您可能无法获得所需的加速效果,因为线程需要将其访问同步到arrayofindex
。
注意:此问题与递归无关。如果您将代码修改为迭代而不是递归,那么您将遇到完全相同的问题-我本人实际上会在我希望提高性能的情况下这样做,尽管我没有在此处进行演示。
有多种方法可以为每个OMP线程分配自己的工作数组。如果必须继续动态分配空间,则应安排在并行区域内部中分配空间,以便每个线程分配自己的空间。但是,如果您愿意并且能够依靠可变长度数组,那么可能唯一需要做的就是将OMP private
子句附加到parallel for
构造上。
例如,您代码上的这种变体对我有用:
void gen_tail(int length, int num_letters, int arrayofindex[], int position) {
for (int letter = 0; letter < num_letters; letter++) {
arrayofindex[position] = letter;
if (position + 1 < length) {
gen_tail(length, num_letters, arrayofindex, position + 1);
} else {
// this is the bottom ... do something with arrayofindex, such as:
#pragma omp critical
{
for (int i = 0; i < length; i++) {
putchar('A' + arrayofindex[i]);
}
putchar('\n');
}
}
}
}
void gen(int length, int num_letters) {
assert(length > 1);
int arrayofindex[length]; // Note: VLA, _not_ dynamically allocated
// Marking the array 'private' means each thread gets its own copy.
// This would not have the needed effect if 'arrayofindex' were a pointer.
#pragma omp parallel for private(arrayofindex)
for (int letter = 0; letter < num_letters; letter++) {
arrayofindex[0] = letter;
gen_tail(length, num_letters, arrayofindex, 1);
}
}
int main(void) {
gen(5, 4);
}
这为我发出了预期的1024(== 4 5 )个结果,所有这些都是不同的,因为我有充分的理由期望它应该做。