2012-06-13 36 views
3

我对OpenMP相当陌生,所以这可能有一个简单的答案,但我一直无法找到它。OpenMP:锁定对单个数组元素的访问权限?

假设我有以下C代码,并且想要使用OpenMP进行并行化。 A是一个具有小于1的double值的对象数组,是一个链表的数组,append将一个指针添加到链表的末尾。

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

问题是,多个线程可能试图将项目追加到给定的存储桶一次。我可以让这个附加语句至关重要。但是,在我的应用程序中,我可能会有大约1000个存储桶,所以大多数时间线程将在不同的存储桶上运行。

是否有强制锁定桶的各个元素的方法?或者处理这个问题的其他方式?

回答

7

那么,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; 
} 

或者,如果粒度的该级别比你需要的,你可以阻止阵列的区域等

+0

+1我完全忘了更关于OpenMP锁定原语。 –

2

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

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