我正在尝试并行化一部分包含嵌套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)
这段代码作为一个顺序程序可以正常工作。
任何线程都可以在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位的情况下,我肯定是把生成的结果移到了内存中,而不是从磁盘上处理。