2

我有一个代码的并行部分,它使用派生类型的 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 上本地分配吗?如果是这样,还有什么可以解释这种行为?否则,我该如何强制数据本地化?

谢谢

4

0 回答 0