仅当存在数据争用与锁定时,OpenMP临界区?

时间:2018-03-26 20:40:11

标签: c++ openmp

我的问题与此问题有些类似:How to use lock in OpenMP? 从某种意义上说,他们的回答有点回答我的问题,但不够好。

我正在尝试在OpenMP中实现一个简单的工作窃取调度程序(从头开始)。

假设我有一个对象的数组,比如说int。我有多个线程来操作这个数组的条目,没有特别的顺序。我想确保没有两个线程同时尝试访问该数组的相同元素。但是,我允许线程访问相同的元素,只要访问不是同时的。此外,我允许线程同时访问阵列,只要每个线程希望在此期间访问阵列的不同条目。我可以使用一个关键部分,如下所示:

int array[1000];

#pragma omp parallel
{
    bool flag = true;
    while(flag){
        int x = rand()%1000;
        #pragma omp critical
        {
            array[x] = some_function(array[x]);
            if (some_condition(array[x])){
                flag = false;
            }
        }

    }

}

此代码创建一些线程,线程随机访问和操作数组的条目,直到某些停止条件杀死线程。这段代码工作正常,因为临界区确保没有两个线程同时写入数组(如果它们生成相同的x值)。但是,如果在某个时间没有两个线程生成相同的x值,则临界区是冗余的,因为它们的线程不访问相同的条目。是否有一种方法可以使线程停止当且仅当它生成的x的值与当前也使用x的线程相同时?现在,这段代码效率很低,基本上是串行的,即使每个线程都会生成不同的x值。我想这样做,只有在发生碰撞时它们才会失速。

也许我正在寻找的是锁,但我不确定。关键部分不是正确的方式去这里吗?

1 个答案:

答案 0 :(得分:1)

我的意思是这样的:

#include <stdlib.h>
#include <omp.h>

int main() 
{
    int array[1000];
    omp_lock_t locks[1000];

    for (int i = 0; i < 1000; i++)
        omp_init_lock(&locks[i]);

    #pragma omp parallel
    {
        bool flag = true;
        while(flag){
            int x = rand()%1000;
            omp_set_lock(&locks[x]);
            array[x] = some_function(array[x]);
            if (some_condition(array[x])){
                flag = false;
            }
            omp_unset_lock(&locks[x]);
        }

    }

    for (int i = 0; i < 1000; i++)
        omp_destroy_lock(&locks[i]);
}