我有一个代码的并行部分,它使用派生类型的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个线程。
私人的数量级“n”很小(小于10),而每个“foo”的“昏暗”大约是数百万的数量级。
我从这种行为中猜测,由于CPU之间的连接,访问内存存在一些瓶颈。奇怪的是,如果我单独测量执行HEAVYSTUFF和COPYSTUFFONSHARED所需的时间,那么HEAVYSTUFF会慢下来,而COPYSTUFFONSHARED会有一个“近乎线性”的加速。
问题是:我确定THREADPRIVATE派生类型中的内存实际上将在本地分配给该线程所属的CPU吗?如果是这样,还有什么可以解释这种行为?否则,我如何强制数据本地化?
谢谢