OpenMP无法使用数组访问间接

时间:2015-08-07 18:10:32

标签: arrays parallel-processing fortran openmp

我正在尝试使用OpenMP以并行方式优化循环。

  DOUBLE PRECISION, INTENT(INOUT) :: X(13541)
  INTEGER         , INTENT(IN)    :: NELEM,NELMAX !NELMAX = 25996 
  INTEGER         , INTENT(IN)    :: IKLE(NELMAX)
  DOUBLE PRECISION, INTENT(IN)    :: W(NELMAX)
!$OMP PARALLEL DO PRIVATE(IELEM) REDUCTION(+:X)
  DO IELEM = 1 , NELEM
    X(IKLE(IELEM)) = X(IKLE(IELEM)) + W(IELEM)
  ENDDO
!$OMP END PARALLEL DO

对于任何不同的I和J,可能是IKLE(I)= IKLE(J)

增加线程数,我发现运行循环需要更长的时间。我使用OMP_GET_WTIME()为作业计时。

1 T  0.21943306922912598     
2 T  0.30610203742980957     
3 T  0.43688893318176270     
4 T  0.53783702850341797     
5 T  0.61055016517639160     
6 T  0.96715998649597168     
7 T  0.89582014083862305     
8 T   1.3073339462280273

我认为问题是由数据访问间接引起的,但我不知道如何在OpenMP中处理它

1 个答案:

答案 0 :(得分:1)

如果可能是IKLE(I)= IKLE(J)那么你遇到的问题比不规则访问更糟糕,无法有效使用缓存数据,你有一个数据竞赛 - 您的代码中没有保护措施,防止多个线程同时写入同一位置。根据{{​​1}}的出现频率,您可能会很幸运,并且在实践中从未体验过这场比赛。或者你可能会不走运。无论哪种方式,正如所写,该程序是错误的'un。

FWIW我同意你的怀疑,即访问X元素的不规则模式是你报告的时间特性的根源,它需要通过缓存进行更多的数据移动。

另外,在我写作的时候,这一行

  INTEGER, INTENT(IN) :: NELEM,NELMAX = 25996

也是错误的,尝试初始化例程参数是一个语法错误。

编辑,回应OP的评论:

依赖肯定是另一个问题 - 不是我的思维方式,依赖(通过我认为我称之为数据竞争)会使程序错误,破坏,错误。糟糕的缩放只是一个不便。问题出现在OpenMP版本的程序中,因为两个或更多线程可能会在同一时间尝试更新X的相同元素。更新不是原子的,在幕后进行的各种操作(将数据读取到寄存器,将值一起添加到两个寄存器中,将数据写入存储器位置,这类事物)可以以任何方式交错,大多数交错都不会像X那样将值保留在程序的顺序执行中。

您是否会对您所说的数据移动提供一些提示?目前还没有写好。