Fortran中的OpenMP产量损失

时间:2014-02-19 12:52:57

标签: multithreading performance fortran openmp

首先抱歉,如果我犯了语法错误。我不是英国人。

我正在努力改善在Fortran中使用OpenMP增加线程数时发生的产量损失。

我正在使用两个Intel Xeon X5650(12个物理内核)和96 Gb RAM

我获得的最佳结果如下:

1 proc - > 15.50秒; 2 proc - > 8.10秒; 4 proc - > 4.42秒; 8 proc - > 2.81秒; 12 proc - > 2.43秒

就像你看到的那样,改进减少了我运行的线程越多。

以下是代码:

allocate(SUM(PUNTOST,PUNTOSP,NUM_DATA,2))
allocate(SUMATORIO(1))
allocate(SUMATORIO(1)%REGION(REGIONS))
DO i=1,REGIONES
    allocate(SUMATORIO(1)%REGION(i)%VALOR(2,PUNTOSP,PUNTOST))
    SUMATORIO(1)%REGION(i)%VALOR= cmplx(0.0,0.0)
END DO
allocate(valor_aux(2,PUNTOSP,PUNTOST))

!...

call SYSTEM_CLOCK(counti,count_rate) 

!$OMP PARALLEL NUM_THREADS(THREADS) DEFAULT(PRIVATE) FIRSTPRIVATE(REGIONS) &
!$OMP SHARED(SUMATORIO,SUM,PP,VEC_1,VEC_2,IDENT,TIPO,MUESTRA,PUNTOST,PUNTOSP) 
!$OMP DO SCHEDULE(DYNAMIC,8)
DO i=1,REGIONS
    INDICE=VEC_1(i) 
    valor_aux = cmplx(0.0,0.0)
    DO j=1,VEC_2(i)     
        ii=IDENT(INDICE+1)
        INDICE=INDICE+1     
        IF(TIPO(ii).ne.4) THEN   
            j1=MUESTRA(ii)
            DO I1=1,PUNTOST
                DO I2=1,PUNTOSP
                valor_aux(1,I2,I1)=valor_aux(1,I2,I1)+SUM(I1,I2,J1,1)*PP(ii)
                valor_aux(2,I2,I1)=valor_aux(2,I2,I1)+SUM(I1,I2,J1,2)*PP(ii)
                END DO 
            END DO  
        END IF 
    END DO
    SUMATORIO(1)%REGION(i)%VALOR= valor_aux
END DO
!$OMP END DO
!$OMP END PARALLEL 

call SYSTEM_CLOCK(countf)
dt=REAL(countf-counti)/REAL(count_rate)
write(*,*)'FASE_1: Time: ',dt,'seconds'

要知道的一些要点:

  • 除循环向量
  • 外,所有数据类型均为COMPLEX
  • NUM_DATA = 14000000
  • REGIONS = 1000000
  • VEC_2中包含的值介于10到20之间
  • PUNTOST = 21
  • PUNTOSP = 20
  • 所有分配的内存消耗大约60 Gb的RAM

我试图改变矩阵的尺寸以避免过度的内存缓存(例如,SUM(2,PUNTOSP,PUNTOST,NUM_DATA))但这是我获得最佳性能的方式(我不喜欢我不知道原因,因为在我读过的大多数文档中,他们都说你必须尝试使内存访问“顺序”,以使CPU为缓存带来最少的内存量。

此外,我已将内存对齐更改为32,64和128字节,但它没有任何改进。

此外,我已将SCHEDULE选项更改为具有不同块大小的STATIC和具有不同块大小的DYNAMIC,但结果相同或更差。

在使用8个或更多内核时,您是否有一些我可以用来改善性能的想法?

非常感谢你的关注和帮助。

2 个答案:

答案 0 :(得分:1)

使用12个处理器将CPU时间除以6相当不错。在我的应用程序中,我很少得到超过4或5(但它始终是顺序部分,这可能是其中的原因)。

您可以尝试选项折叠,允许将两个循环合并在一起......但我不知道在您的情况下这是否可行,因为它们是要满足的条件(例如,两个循环之间没有指令)。

答案 1 :(得分:0)

在Fortran中处理多维数组时,最左边的索引应该更快。您可以尝试将valor_auxSUM的索引顺序更改为

valor_aux(PUNTOSP, PUNTOST, 2)
SUM(PUNTOSP, PUNTOST, NUM_DATA, 2)

此外,您应该始终关注Amdahl's law。总会有一些开销,无法实现额外的加速。

另外:在你的两个最里面的循环中,因子PP(ii)不会改变。您应该尝试在这些循环之后应用它(除了,您知道,您正在使用FMA)。而这些循环只是许多值的SUM。您应该尝试使用内部函数SUM来删除这些循环。这两件事都需要对你的循环进行大规模的重新设计。