admin管理员组文章数量:1531425
问题描述:
这是一段给链表添加节点的函数:
void addToList(int data)
{
item_t * newItem = (item_t *) malloc(sizeof(item_t));
newItem->data = data;
newItem->next = NULL;
// Find tail and add newItem to it.
if(head == NULL) // i.e. list is empty .
{
head = newItem;
}
else // Find end of list and add to it.
{
item_t *tail = head;
while (tail->next != NULL){
tail = tail->next;
}
tail->next = newItem;
}
}
并行化调用addToList函数:
#pragma omp parallel for
for(i = 0; i < numAdd; i++){
addToList ( i );
}
但在运行后发现,一些元素并没有如期加入链表,而是直接丢失了。此外,那些丢失的元素也会占用空间,且这些空间没有被释放。这不满足tread safe的条件。
注意: thread safe不意味着高效率,很多时候都会牺牲效率来成全thread safe。
造成以上问题的原因:
1. *head 头指针是被多个线程共享的,可能会导致data race。例如:
线程A认为head == NULL,希望把值1赋给head,
同时线程B也认为head == NULL,并率先把值2赋给head
线程A再把值赋给head,覆盖掉了线程B的操作,最终导致2这个值丢失。
2. *tail指针是被多个线程共享的,可能会导致data race。情况类似头指针。
那能否用OpenMP(二)并行运算中的数据依赖问题中解决data race的方法来解决这个问题呢?
如果把*head指针或*tail变成private的,是不可行的,因为这两个指针是整个链表共享的,不是每个线程私有的。
解决方法:使用#pragma omp critical{ }
这行代码的作用是,在{ }范围内的代码属于critical region。
#pragma omp critical
{
... //critical region
}
如果有某个线程率先达到了critical region, 其他线程就不能进入这个区域,直到占领这个区域的线程离开。
改法1:在调用addToList函数处使用#pragma omp critical{ }。
#pragma omp parallel for
for(i = 0; i < numAdd; i++){
#pragma omp critical
{
addToList(i);
}
}
但这种方法是低效的,因为在代码执行过程中,只有一个线程可以抵达critical region,这本质上和按顺序执行没有区别。
改法2:在addToList函数中使用#pragma omp critical{ }。
在addToList函数中添加critical region。由于函数的前三步不存在多线程data race问题,每个线程都需要独立创造空间存放数据和指针,所以不需要将其纳入cirtical region。
void addToList(int data)
{
item_t * newItem = (item_t *) malloc(sizeof(item_t));
newItem->data = data;
newItem->next = NULL;
#pragma omp parallel for
{
// Find tail and add newItem to it.
if(head == NULL) // i.e. list is empty .
{
head = newItem;
}
else // Find end of list and add to it.
{
item_t *tail = head;
while (tail->next != NULL){
tail = tail->next;
}
tail->next = newItem;
}
}
}
由于函数的前三步是并行执行的,改法2比改法1效率有所提升,但也称不上高效。
使用#pragma omp critical{ }的其他注意点:
1. 无法直接嵌套critical region,因为这两个critical region会使用同一个锁。
#pragma omp critical
{
...
#pragma omp critical
{
...
}
}
2. 可以通过给critical region命名来嵌套使用。这时,每个critical region都会拥有自己独有的锁。
#pragma omp critical (OUTER)
{
...
#pragma omp critical (INNER)
{
...
}
}
版权声明:本文标题:OpenMP(三)#pragma omp critical 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1726268871a1063571.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论