【问题标题】:Parallelization of Intel Fortran code for allocatable type containing pointer arrays using OpenMP使用 OpenMP 对包含指针数组的可分配类型的英特尔 Fortran 代码进行并行化
【发布时间】:2020-05-24 05:45:44
【问题描述】:

我正在尝试并行化包含嵌套 do 循环的部分代码。嵌套循环中有一个“READ”操作。我正在尝试使用 openMP 来减少计算的墙时间。 我有一个包含可分配指针的类型。我不确定如何处理错误消息,当我尝试使用时,我收到“当指针 CellArr 未与目标关联时尝试使用它” P_ph(iph,iel)%cellArr(igp)%arr 在这个嵌套循环之外。

OPEN (24, FILE=TRIM(ADJUSTL(InpFile))//"_GSP.dat", STATUS='OLD', ACTION='READ', &
ACCESS='DIRECT', FORM='FORMATTED', RECL=600*nel)   

!$omp parallel private(id,iel,iph,igp,igp1,tmpP,lineNo,isegel,iSegEls,ngp,ngp1,P_ph, &
  isegelTmp, igpTmp, phPolVec, integrand) shared(ShapeFunc_P, ElConn, nph) 
id=omp_get_thread_num()
!$omp do
DO iel = 1, nel     
    ngp = elConn(iel)%ngp   

    DO iph = 1, nph  
        ALLOCATE( P_ph(iph, iel)%cellArr(ngp) ) 
    END DO 

    DO igp = 1, ngp                
       lineNo = SUM( elConn(1:iel-1)%ngp ) + igp        
        READ(24,FMT=101,REC=lineNo ) isegelTmp, igpTmp, phPolVec

        DO iph = 1, nph     
           ALLOCATE( P_ph(iph,iel)%cellArr(igp)%arr(ndim,ndim) )
           tmpP = 0.d0 

           DO isegels = 1, Seg_P(iph)%segSize                   
              isegel = Seg_P(iph)%els(isegels)              
              ngp1 = elConn(isegel)%ngp                 
              ALLOCATE( integrand(ngp1) )           
              !Retrieve the PhP function from .dat file             
              phP = RESHAPE( SOURCE = phPolVec((isegel-1)*ndim*ndim+ &
              1:isegel*ndim*ndim ),SHAPE=(/ndim,ndim/) ) / elConn(isegel)%vol       

              DO igp1 = 1, ngp1             
                 ALLOCATE( integrand(igp1)%arr(ndim,ndim) )             
                 integrand(igp1)%arr = phP*ShapeFunc_P(isegel)      
              END DO   

              CALL INTEGRAL( tmpP, integrand, elConn(isegel)%jacobian, ngp, nsd, ndim)      

              DO igp1=1, ngp1           
                 DEALLOCATE( integrand(igp1)%arr )      
              END DO        
              DEALLOCATE(integrand) 
           END DO 

           P_ph(iph,iel)%cellArr(igp)%arr = tmpP
       END DO
     END DO
END DO
!$omp end do
!$omp end parallel
CLOSE (24)

种类如下:

TYPE CELL
    REAL*8, POINTER :: arr(:,:) 
END TYPE CELL 
TYPE CELL2  
    TYPE (CELL), POINTER :: CellArr(:) 
END TYPE CELL2
TYPE (CELL2) :: P_ph(nph, nel)

此代码作为顺序程序运行良好。

【问题讨论】:

  • P_ph 应该共享,因为您可以从所有数组中访问其元素。
  • Fortran I/O 是否保证是线程安全的?我肯定会在更进一步之前检查一下 - 我的猜测不是
  • 还要检查 SHARED (nel, ndim, nsd, P_ph, Seg_P) PRIVATE (phP)。 DEFAULT (NONE) 是一个很好的诊断。 P_ph 随着 ALLOCATE 不断增长
  • @PierredeBuyl:谢谢。根据您的建议,我不再收到错误消息。但是,结果似乎不是线程安全的。
  • 我没有这方面的直接来源,但我想 OpenMP 区域中的文件 I/O 无论如何都是一个的想法。可以提前读取数据吗?

标签: fortran openmp intel-fortran


【解决方案1】:

任何线程都可以作用于单元 24 上文件中的任意记录是否有意义? 如果是这样,将读取放在 !$OMP CRITICAL 区域中可能会更好。

我还注意到该文件是 FORMATTED 和 DIRECT,可以通过 REC=lineNo 和 RECL=600*nel 访问。 (不寻常的记录大小,这是在运行吗?文件大小是600*nel * sum(elConn(1:nel)%ngp),看起来非常大的顺序(nel^2)。

在进入 !$OMP 区域之前,最好将此信息创建为 (isegelTmp, igpTmp, phPolVec) 的共享派生类型数组,然后从任何线程“随机”处理。 (没有说明这 3 个组件的类型或大小。) 什么是记录 ID:SUM(elConn(1:iel-1)%ngp) + igp?处理时是否会发生变化(可能不会)?在进入 !OMP 区域之前,最好为每个“iel”的第一条记录创建一个共享索引,并使用它来定义任何线程对每个“iel”的工作。 每个“iel”的所有信息在哪里?在另一个共享的直接访问文件上?

我还没有回答多线程随机读取直接访问文件是否是线程安全的问题?我没有尝试过,但 !$OMP CRITICAL 是最低要求。你可以试一试。 (大量磁盘缓冲区冲突)首先创建共享内存数据结构要安全得多。希望每个 iel 处理时间比阅读时间长得多。 处理后的结果去哪里了?到同一个直接访问文件?解决问题?

这看起来像一个结果处理循环。在我的分析中,我没有将其移至 !$OMP,因为此结果处理往往比结果计算阶段快得多。对于 64 位,我当然已经将生成的结果移动到内存,而不是从磁盘处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 2014-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多