【发布时间】:2014-02-19 21:41:42
【问题描述】:
如果我犯了语法错误,首先抱歉。我不是英国人。
我正在尝试改善在 Fortran 中使用 OpenMP 增加线程数时发生的产量损失。
我正在使用两个配备 96 Gb RAM 的 Intel Xeon X5650(12 个物理内核)
我获得的最佳结果如下:
1 触发 -> 15.50 秒; 2 过程 -> 8.10 秒; 4 过程 -> 4.42 秒; 8 过程 -> 2.81 秒; 12 次触发 -> 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
- 地区 = 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 个或更多内核时的性能吗?
非常感谢您的关注和帮助。
【问题讨论】:
标签: multithreading performance fortran openmp