OpenMP 任务与数据环境

3

我正在尝试为我的C++/OpenMP程序使用任务结构:

#pragma omp parallel
    {
        typename ClusterNormal<DIM>::VectorMean ResultMeanThread;
        ResultMeanThread.setZero();
        #pragma omp single
        for(list<unsigned int>::const_iterator it=IDLeft.cbegin(); it!=IDLeft.cend(); it++)
        {
            #pragma omp task
            {
                ResultMeanThread += Data[*it];
            }
        }
}

这段代码计算了一些VectorMean (不考虑它们是什么,但它们定义了+运算符)在IDLeft所示的数据元素上的总和。
每个线程都用全零初始化VectorMean。我的问题是,在for循环之后,ResultMeanThread仍然由全零组成。
当一个任务被执行时,总和被正确计算,但在任务执行后,ResultMeanThread总是重新初始化为零。
我该怎么修复它?我正在使用任务因为有列表,但我的代码不起作用。

ResultMeanThread 应该在并行区域之前声明,并标记为共享变量,这样才合适。另外,将 += 操作应用于 VectorMean 类型的对象,在并行环境下是否安全? - Piotr Skotnicki
我已经为每个线程创建了私有的ResultMeanThread。我认为在共享变量上使用+=运算符不是一个好主意,因为会存在竞争条件... - Darko
在这段代码之后,使用单个构造将ResultmeanThread的总和计算出来。 - Darko
你能展示一下之后会发生什么吗? - Piotr Skotnicki
找到答案了。感谢您的帮助:错误在于将ResultMeanThread视为私有,就像您在第一条评论中发布的那样。 - Darko
显示剩余2条评论
1个回答

1
我发现问题在于声明了ResultMeanThread为私有变量。我尝试了下面这段代码,将ResultMeanThread的向量声明为共享变量(向量长度为线程数量),这样每个线程只能访问向量中的一个元素(没有竞争条件)。
在之前的代码中,每个ResultMeanThread都是零,因为task结构。每次执行task时,私有变量被设置为它们的初始值。我必须使用task结构,因为我使用了list
以下是代码:
vector<typename ClusterNormal<DIM>::VectorMean> ResultMeanThread;
typename ClusterNormal<DIM>::VectorMean ResultMeanFinal;

//here i set initial values to zero, and number of vector elements equal to total number of threads

#pragma omp parallel
{
    #pragma omp single
    for(list<unsigned int>::const_iterator it=IDLeft.cbegin(); it!=IDLeft.cend(); it++)
    {
        #pragma omp task
        {
            ResultMeanThread[omp_get_thread_num()] += Data[*it];
        }
    }
    #pragma omp taskwait

    // Final sum
    #pragma omp critical
    {
        ResultMeanFinal+=ResultMeanThread[omp_get_thread_num()];
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接