为何移除该barrier会引发race condition?为何其可消除竞态条件?
关于OpenMP代码中Barrier与竞态条件的分析
先明确这段代码的核心执行逻辑:
- 外层开启4线程的
parallel区域,并行执行10轮i循环 - 每轮
i循环内,先通过parallel for再启动4线程执行10次j循环,每个j迭代用critical保护共享变量sum的自增操作 - 最后通过
single指令让某一个线程对sum再做一次自增
一、移除Barrier时产生竞态条件的原因
外层的4个线程是并行跑i循环的,当某一个线程做完自己的parallel for(包括所有critical里的sum +=1)后,会直接进入single块执行sum +=1。但这时候,其他外层线程可能还在执行自己的parallel for中的critical操作——也就是有的线程还在给sum加1,而已经完成的线程已经开始修改sum了。
这就造成了两类无同步的操作同时修改共享变量:critical里的自增和single里的自增。没有同步机制保证它们的执行顺序,最终sum的结果会因为线程执行时机的不同而不确定,也就是出现了竞态条件。
举个实际场景:线程A刚做完10次j循环的自增,立刻执行single给sum加1;此时线程B还在跑j循环的第3次critical自增,两个操作同时改sum,就会出现数值被覆盖、计算错误的情况。
二、启用Barrier后消除竞态的原因
#pragma omp barrier是一个强制同步点,它要求所有外层线程必须等其他所有线程都完成了barrier之前的全部操作,才能继续往下执行。
把barrier放在parallel for和single之间后:
- 所有外层线程都得先完成自己的
parallel for(包括所有critical里的sum +=1) - 等所有线程都到了barrier这个同步点,才会一起进入后续的
single环节
这样一来,single里的sum +=1是在所有j循环的自增操作彻底结束后才执行的,不会和任何critical操作同时修改sum;再加上single本身只会让一个线程执行,不存在多个线程同时执行这个自增的情况,竞态条件自然就被消除了,sum的结果会变成确定值。
内容的提问来源于stack exchange,提问作者Niteya Shah
相关产品推荐
相关产品推荐

