代码之家  ›  专栏  ›  技术社区  ›  user308485

仅当存在数据争用vs锁定时才打开MP关键部分?

  •  0
  • user308485  · 技术社区  · 6 年前

    我的问题与此类似: 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 回复  |  直到 6 年前
        1
  •  1
  •   Janez Kuhar    6 年前

    我的意思是这样的:

    #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]);
    }