arrays - Fortran 中大型数组的 OpenMP 缩减
问题描述
我知道有时会问到与此类似的问题:Openmp array reductions with Fortran,Reducing on array in OpenMP,甚至在英特尔论坛(https://software.intel.com/en-us/forums/intel-moderncode-for -parallel-architectures/topic/345415)但我想知道您的意见,因为我得到的可扩展性不是我所期望的。
所以我需要填充一个非常大的复数数组,我想与 OpenMP 并行化。我们的第一种方法是这样的:
COMPLEX(KIND=DBL), ALLOCATABLE :: huge_array(:)
COMPLEX(KIND=DBL), ALLOCATABLE :: thread_huge_array(:)
INTEGER :: huge_number, index1, index2, index3, index4, index5, bignumber1, bignumber2, smallnumber, depending_index
ALLOCATE(huge_array(huge_number))
!$OMP PARALLEL FIRSTPRIVATE(thread_huge_array)
ALLOCATE(thread_huge_array(SIZE(huge_array)))
thread_huge_array = ZERO
!$OMP DO
DO index1=1,bignumber1
! Some calculations
DO index2=1,bignumber2
! Some calculations
DO index3=1,6
DO index4=1,6
DO index5=1,smallnumber
depending_index = function(index1, index2, index3, index4, index5)
thread_huge_array(depending_index) = thread_huge_array(depending_index)
ENDDO
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END DO
!$OMP BARRIER
!$OMP MASTER
huge_array = ZERO
!$OMP END MASTER
!$OMP CRITICAL
huge_array = huge_array + thread_huge_array
!$OMP END CRITICAL
DEALLOCATE(thread_huge_array)
!$OMP END PARALLEL
因此,通过这种方法,我们可以在 8 核之前获得良好的可扩展性,在 32 核之前获得合理的可扩展性,从 40 核开始,它比 16 核慢(我们有一台具有 80 个物理核的机器)。当然,我们不能使用 REDUCTION 子句,因为数组的大小太大以至于无法放入堆栈(甚至将 ulimit 增加到机器允许的最大值)。
我们尝试了一种不同的方法:
COMPLEX(KIND=DBL), ALLOCATABLE :: huge_array(:)
COMPLEX(KIND=DBL), POINTER:: thread_huge_array(:)
INTEGER :: huge_number
ALLOCATE(huge_array(huge_number))
ALLOCATE(thread_huge_array(SIZE(huge_array),omp_get_max_threads()))
thread_huge_array = ZERO
!$OMP PARALLEL PRIVATE (num_thread)
num_thread = omp_get_thread_num()+1
!$OMP DO
DO index1=1,bignumber1
! Some calculations
DO index2=1,bignumber2
! Some calculations
DO index3=1,6
DO index4=1,num_weights_sp
DO index5=1,smallnumber
depending_index = function(index1, index2, index3, index4, index5)
thread_huge_array(depending_index, omp_get_thread_num()) = thread_huge_array(depending_index, omp_get_thread_num())
ENDDO
ENDDO
ENDDO
ENDDO
ENDDO
!$OMP END DO
!$OMP END PARALLEL
huge_array = ZERO
DO index_ii = 1,omp_get_max_threads()
huge_array = huge_array + thread_huge_array(:,index_ii)
ENDDO
DEALLOCATE(thread_huge_array)
DEALLOCATE(huge_array)
在最后一种情况下,我们为该方法获得了更长的时间(由于分配了更大的内存)和更差的相对加速度。
您能否提供一些提示以实现更好的加速?或者用 OpenMP 来处理这些巨大的数组是不可能的?
解决方案
推荐阅读
- java - 致命错误编译:无效标志:--release java 8
- flutter - 颤振测试仪..点击不工作。如何解决“Bad state: No element”错误?
- node.js - 进行更改时,Gulp 不会重新编译 sass
- reactjs - InitelliJ Idea、ReactApp 和 Flow:意外令牌
- heroku - Heroku 未在 Okta OAuth 2.0 PKCE VueJs 应用程序中应用环境变量更改
- python - 此代码如何使用数字将字母标识为大写或小写
- python - 使用字符串插值在 for 循环下的多行字符串中追加元素
- c++ - 如何正确将“字符串”转换为“双精度”?
- python - 如何使用 Python 在 imo.im 中自动发送消息?我在网上找不到 imo.im api
- asp.net - 对现有用户进行 Microsoft 身份验证