如何在OpenMP中避免线程索引一维数组时的伪共享问题
解决OpenMP一维数组的伪共享问题
问题背景
我有一个大小由OpenMP线程数决定的一维数组(使用Fortran编写,该问题同样适用于C/C++)。假设整数numThreads为OpenMP线程数(可作为输入使数组可分配),数组exArray的大小为numThreads。每个线程会调用子例程exSubroutine()操作exArray对应索引的元素,初始代码如下:
integer :: numThreads integer :: exArray(numThreads) integer :: iThread subroutine exSubroutine(a) integer, intent(in out) :: a end subroutine !$OMP parallel private(iThread) iThread = omp_get_thread_num() + 1 call exSubroutine(exArray(iThread)) ! more code here that uses/writes to exArray(iThread) maybe several more times !$OMP end parallel
由于**伪共享(False sharing)**问题,CPU会将整个数组加载到缓存,导致数组在不同CPU缓存间频繁切换。
已尝试的优化方案
我尝试用每个线程的私有变量先复制数组元素,操作后再写回的方法优化,代码如下:
integer :: numThreads integer :: exArray(numThreads) integer :: iThread, privVar subroutine exSubroutine(a) integer, intent(in out) :: a end subroutine !$OMP parallel private(iThread, privVar) iThread = omp_get_thread_num() + 1 privVar = exArray(iThread) call exSubroutine(privVar) ! more code here that uses/writes to privVar maybe several more times exArray(iThread) = privVar !$OMP end parallel
该方法确实提升了性能,但仍需至少一次对exArray(iThread)的写入操作。
需求
我需要保留大小为numThreads的exArray状态,也了解数组填充等技巧,但希望找到无需复杂技巧的OpenMP指令或方法,让编译器识别每个线程仅需操作数组单个元素,避免伪共享。此外,我发现程序中的二维数组(如dimension(1000, numThreads)的exArray)不存在该问题,推测是因无法装入单个缓存行。
内容的提问来源于stack exchange,提问作者user23399617
相关产品推荐
相关产品推荐

