我有一个代码的并行部分,它使用派生类型的 THREADPRIVATE ALLOCATABLE 数组,该数组又包含其他 ALLOCATABLE 变量:
MODULE MYMOD
TYPE OBJ
REAL, DIMENSION(:), ALLOCATABLE :: foo1
REAL, DIMENSION(:), ALLOCATABLE :: foo2
END TYPE
TYPE(OBJ), DIMENSION(:), ALLOCATABLE :: priv
TYPE(OBJ), DIMENSION(:), ALLOCATABLE :: shared
!$OMP THREADPRIVATE(priv)
END MODULE
每个线程使用变量“priv”作为大量计算的缓冲区,然后将其复制到共享变量上。
MODULE MOD2
SUBROUTINE DOSTUFF()
!$OMP PARALLEL PRIVATE(n,dim)
CALL ALLOCATESTUFF(n,dim)
CALL HEAVYSTUFF()
CALL COPYSUFFONSHARED()
!$OMP END PARALLEL
END SUBROUTINE DOSTUFF
SUBROUTINE ALLOCATESTUFF(n,dim)
USE MYMOD, ONLY : priv
ALLOCATE(priv(n))
DO i=1,i
ALLOCATE(priv(i)%foo1(dim))
ALLOCATE(priv(i)%foo2(dim))
ENDDO
END SUBROUTINE ALLOCATESTUFF
SUBROUTINE COPYSTUFFONSHARED()
USE MYMOD
...
END SUBROUTINE COPYSTUFFONSHARED
SUBROUTINE HEAVYSTUFF()
USE MYMOD, ONLY : priv
...
END SUBROUTINE HEAVYSTUFF
END MODULE
我在一台有两个 CPU 的机器上运行这段代码,每个 CPU 有 10 个内核,当超过 10 个线程的限制时,我遇到了很大的性能损失:基本上,代码线性扩展到 10 个线程,然后在这个障碍之后,坡度大大降低。我在一台有 8 个 CPU 的机器上获得了非常相似的行为,每个 CPU 有 4 个内核,但这次损失大约是 5/6 个线程。
由于 priv 的数量级“n”很小(小于 10),而每个“foo”的“dim”大约是几百万。
我从这种行为中猜想,由于 CPU 之间的连接,访问内存存在某种瓶颈。奇怪的行为是,如果我分别测量执行 HEAVYSTUFF 和 COPYSTUFFONSHARED 所需的时间,那么 HEAVYSTUFF 会减慢速度,而 COPYSTUFFONSHARED 具有“几乎线性”的加速。
问题是:我确定 THREADPRIVATE 派生类型中的内存实际上会在线程所属的 CPU 上本地分配吗?如果是这样,还有什么可以解释这种行为?否则,我该如何强制数据本地化?
谢谢