OpenMP:锁定对单个数组元素的访问?

Posted

技术标签:

【中文标题】OpenMP:锁定对单个数组元素的访问?【英文标题】:OpenMP: Locking access to single array elements? 【发布时间】:2012-06-13 15:05:38 【问题描述】:

我对 OpenMP 还很陌生,所以这可能有一个简单的答案,但我一直没能找到它。

假设我有以下 C 代码并希望使用 OpenMP 将其并行化。 A 是一个对象数组,其中一些 double 值小于 1 buckets 是一个链表数组,并且 append 将一个指向对象的指针添加到链表的末尾。

#pragma omp for 
for (i = 0; i < n; ++i) 
    x = (int) (A[i].val * NUM_BUCKETS);
    append(&A[i], buckets[x]);
 

问题是多个线程可能同时尝试将项目附加到给定存储桶。我可以使附加语句变得至关重要。但是,在我的应用程序中,我可能会有大约 1000 个桶,因此大部分时间线程将在不同的桶上运行。

有没有办法对存储桶的各个元素强制执行锁定?或者其他处理方式?

【问题讨论】:

【参考方案1】:

好吧,OpenMP 不能自动为您完成,但它允许您创建自己的锁定变量,您可以使用这些变量来限制对数组元素的访问;例如,每个数组元素可以有一个锁:

#include <stdio.h>
#include <omp.h>


int main(int argc, char **argv)

    const int NITEMS=20;
    int array[NITEMS];
    omp_lock_t lock[NITEMS];

    for (int i=0; i<NITEMS; i++)
        omp_init_lock(&(lock[i]));

#pragma omp parallel for shared(array, lock) default(none)
     for (int i=0; i<NITEMS; i++) 
        int tid = omp_get_thread_num();
        int item = (i * 7) % NITEMS;

        omp_set_lock(&(lock[item]));
        array[item] = tid;    // only one thread in here at a time; others block at set_lock()
        omp_unset_lock(&(lock[item]));
    

    for (int i=0; i<NITEMS; i++)
        printf("%3d ", array[i]);
    printf("\n");

    for (int i=0; i<NITEMS; i++)
        omp_destroy_lock(&(lock[i]));


    return 0;

或者,如果该粒度级别超出您的需要,您可以阻塞数组的区域等。

【讨论】:

@Jonathan 如果事先不知道 NITEMS 值怎么办?似乎 omp_lock_t lock[NITEMS] 在编译代码之前需要一个常数...... @Ash 你只需分配一个动态大小的数组; omp_lock_t *lock = (omp_lock_t *) malloc(nitems*sizeof(omp_lock_t));左右。【参考方案2】:

OpenMP 不提供细粒度锁定。您可以准备新的列表元素,例如通过将其next 指针设置为NULL 并使用atomic 来保护列表尾指针的更新。这与当前的 OpenMP 实现一样好。

当然,由于 OpenMP 使用底层操作系统线程原语,您可以使用后者提供的任何锁定,例如为每个存储桶使用一组pthreads 互斥锁。缺点是它创建了不可移植的应用程序,但如果效率更重要,您可能愿意牺牲可移植性。

【讨论】:

以上是关于OpenMP:锁定对单个数组元素的访问?的主要内容,如果未能解决你的问题,请参考以下文章

OpenMP:堆数组的性能不佳(堆栈数组工作正常)

c语言如何取数组元素个数?

QByteArray数组的单个元素值的判断

c_cpp OpenMP锁定预订

c ++ OpenMP关键:“单向”锁定?

python数组求和