递归,全局变量和OpenMP

时间:2019-02-25 22:18:05

标签: c recursion parallel-processing

我在调用自己的函数时遇到麻烦 在这种情况下,我不清楚使用openmp进行线程化的正确方法。

code

我这样做的方式,它运行多个线程并且是正确的,但似乎没有没有openmp支持的速度更快。

有办法解决吗?还是因为代码的方式而变得无助。

完整代码https://github.com/e2002e/zhou

1 个答案:

答案 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 )个结果,所有这些都是不同的,因为我有充分的理由期望它应该做。

相关问题