使用OpenMP对包含指针数组的可分配类型的英特尔Fortran代码进行并行化。

问题描述 投票:0回答:1

我正在尝试并行化一部分包含嵌套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)

这段代码作为一个顺序程序可以正常工作。

fortran openmp intel-fortran
1个回答
0
投票

任何线程都可以在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 "的工作。

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

这看起来像是一个结果处理循环。在我的分析中,我没有把它移到 !$OMP,因为这个结果处理往往比结果计算阶段快得多。在64位的情况下,我肯定是把生成的结果移到了内存中,而不是从磁盘上处理。

© www.soinside.com 2019 - 2024. All rights reserved.