Pointers 使用OpenMP时,如何在子例程中分配指针?
如下面的代码示例所示,主程序尝试利用OpenMP调用子例程。在该子例程中,创建并迭代局部指针变量。程序生成数组PTEMPINTLIST的Pointers 使用OpenMP时,如何在子例程中分配指针?,pointers,fortran,openmp,allocation,fortran2003,Pointers,Fortran,Openmp,Allocation,Fortran2003,如下面的代码示例所示,主程序尝试利用OpenMP调用子例程。在该子例程中,创建并迭代局部指针变量。程序生成数组PTEMPINTLIST的下标#1的值208大于207个错误的上限(具体数字各不相同)。我已经将包含用户的派生类型omp private,但似乎调用的子例程中的局部变量也应该声明为omp private,但我不确定这是否正确,我不知道如何实现这一点 你能帮我解释一下为什么程序会出现这样的错误吗?更重要的是,在使用OpenMP时,您能否帮助评论有关如何在子例程中分配指针的最佳实践 不知道为
下标#1的值208大于207个错误的上限(具体数字各不相同)。我已经将包含用户的派生类型omp private
,但似乎调用的子例程中的局部变量也应该声明为omp private
,但我不确定这是否正确,我不知道如何实现这一点
你能帮我解释一下为什么程序会出现这样的错误吗?更重要的是,在使用OpenMP时,您能否帮助评论有关如何在子例程中分配指针的最佳实践
不知道为什么fortran代码没有着色。有人能帮我评论一下如何给代码上色,这样代码更可读吗?
编译器为英特尔Fortran编译器,版本如下:
错误消息如下所示:
代码示例为:
对于主程序中包含的子程序,gfortran给出错误消息:“在文件test_OpenMP.f90/Fortran运行时错误:已修改循环变量的第36行”
显然,“pTempIntList”的大小总是设置为相同的值(在运行之间变化),显然是对随机线程使用大小(aInstance%pIntList)。对于通过该线程的线程来说,它太小。下面是一个有效的版本。对于gfortran和ifort来说,删除“=>null()”似乎是必要的。我不知道是否应该是这样,但由于两个编译器需要它
请尝试以下版本:
module MyModule
type :: MyType
integer, dimension(:), pointer :: pIntList
end type
contains
subroutine IterateList(aInstance)
use omp_lib
integer :: I
type(MyType) :: aInstance
integer, dimension(:), pointer :: pTempIntList
integer :: threadId
threadId = OMP_GET_THREAD_NUM()
allocate (pTempIntList(size(aInstance%pIntList)))
do I = 1, size(pTempIntList)
write (*, *) i, threadID, size(aInstance%pIntList), size (pTempIntList)
pTempIntList(I) = I
end do
end subroutine IterateList
end module MyModule
program TestOpenMP_1_AllocationWithinSubroutines
use MyModule
use omp_lib
implicit none
type(MyType) :: instance
integer :: threadCount
integer :: threadId
integer :: I
!$omp parallel private (instance, threadCount, threadId, I)
threadCount = OMP_GET_NUM_THREADS()
write (*,*) 'Thread numbers are: ', threadCount
threadId = OMP_GET_THREAD_NUM()
allocate (instance%pIntList(200 + threadId))
CALL IterateList(instance)
!$omp end parallel
end program TestOpenMP_1_AllocationWithinSubroutines
对于主程序中包含的子程序,gfortran给出错误消息:“在文件test_OpenMP.f90/Fortran运行时错误:已修改循环变量的第36行”
显然,“pTempIntList”的大小总是设置为相同的值(在运行之间变化),显然是对随机线程使用大小(aInstance%pIntList)。对于通过该线程的线程来说,它太小。下面是一个有效的版本。对于gfortran和ifort来说,删除“=>null()”似乎是必要的。我不知道是否应该是这样,但由于两个编译器需要它
请尝试以下版本:
module MyModule
type :: MyType
integer, dimension(:), pointer :: pIntList
end type
contains
subroutine IterateList(aInstance)
use omp_lib
integer :: I
type(MyType) :: aInstance
integer, dimension(:), pointer :: pTempIntList
integer :: threadId
threadId = OMP_GET_THREAD_NUM()
allocate (pTempIntList(size(aInstance%pIntList)))
do I = 1, size(pTempIntList)
write (*, *) i, threadID, size(aInstance%pIntList), size (pTempIntList)
pTempIntList(I) = I
end do
end subroutine IterateList
end module MyModule
program TestOpenMP_1_AllocationWithinSubroutines
use MyModule
use omp_lib
implicit none
type(MyType) :: instance
integer :: threadCount
integer :: threadId
integer :: I
!$omp parallel private (instance, threadCount, threadId, I)
threadCount = OMP_GET_NUM_THREADS()
write (*,*) 'Thread numbers are: ', threadCount
threadId = OMP_GET_THREAD_NUM()
allocate (instance%pIntList(200 + threadId))
CALL IterateList(instance)
!$omp end parallel
end program TestOpenMP_1_AllocationWithinSubroutines
我认为您遇到了这样一个问题:变量的初始化赋予它save
属性。使用null指针初始化pTempIntList
,意味着它会在子例程的不同调用之间保存。我不确定实现的细节,但可以猜测的是,子例程的所有调用实际上都共享该变量的内存
你也应该认真考虑任何谷歌的评论。使用可分配变量通常比使用指针安全得多。如果可以使用allocatables,那么就使用它们。我认为您遇到了一个问题,即变量的初始化赋予它save
属性。使用null指针初始化pTempIntList
,意味着它会在子例程的不同调用之间保存。我不确定实现的细节,但可以猜测的是,子例程的所有调用实际上都共享该变量的内存
你也应该认真考虑任何谷歌的评论。使用可分配变量通常比使用指针安全得多。如果可以使用可分配表,请使用它们。非常感谢您的解决方案!然而,你知道问题的原因吗?我的意思是,在真实的代码中(比示例更真实一点),仍然会发生这种奇怪的异常。我想知道我是否可以在不破坏你耐心的情况下发布代码(~1000行)…不,我不知道原因。您需要指针还是可以使用可分配的指针?如果一个可分配的将工作,我建议尝试。非常感谢您的解决办法!然而,你知道问题的原因吗?我的意思是,在真实的代码中(比示例更真实一点),仍然会发生这种奇怪的异常。我想知道我是否可以在不破坏你耐心的情况下发布代码(~1000行)…不,我不知道原因。您需要指针还是可以使用可分配的指针?如果一个可分配的将工作,我建议尝试。你不应该有可分配的关键字吗?原因已经写在开始。你说的是什么意思另一个已经被回答了…?
?奇怪错误的原因仍然不清楚,如果你已经阅读了问题,没有官方或可靠的信息来学习如何应对未来的错误。此外,在这里,重点更明确地放在OpenMP如何管理指针类型的分配上。这样做可能会导致你的帖子被标记,这可能会导致版主采取进一步的行动。你不应该有可分配的关键字吗?原因已经在开头写好了。你说的是什么意思另一个已经被回答了…?
?奇怪错误的原因仍然不清楚,如果你已经阅读了问题,没有官方或可靠的信息来学习如何应对未来的错误。此外,在这里,重点更明确地放在OpenMP如何管理指针类型的分配上。这样做可能会导致您的帖子被标记,从而导致版主采取进一步的行动。
module MyModule
type :: MyType
integer, dimension(:), pointer :: pIntList => null ()
end type
end module MyModule
program TestOpenMP_1_AllocationWithinSubroutines
use MyModule
use omp_lib
implicit none
type(MyType) :: instance
integer :: threadCount
integer :: threadId
integer :: I
!$omp parallel private (instance, threadCount, threadId, I)
threadCount = OMP_GET_NUM_THREADS()
write (*,*) 'Thread numbers are: ', threadCount
threadId = OMP_GET_THREAD_NUM()
allocate (instance%pIntList(200 + threadId))
CALL IterateList(instance)
!$omp end parallel
read (*,*)
contains
subroutine IterateList(aInstance)
type(MyType) :: aInstance
integer, dimension(:), pointer :: pTempIntList => null()
integer :: threadId
threadId = OMP_GET_THREAD_NUM()
allocate (pTempIntList(size(aInstance%pIntList)))
do I = 1, size(pTempIntList)
pTempIntList(I) = I
!write (*,*) pTempIntList(I)
write (*,*) 'Thread ',threadId, ' - ',pTempIntList(I)
end do
end subroutine
end program TestOpenMP_1_AllocationWithinSubroutines
module MyModule
type :: MyType
integer, dimension(:), pointer :: pIntList
end type
contains
subroutine IterateList(aInstance)
use omp_lib
integer :: I
type(MyType) :: aInstance
integer, dimension(:), pointer :: pTempIntList
integer :: threadId
threadId = OMP_GET_THREAD_NUM()
allocate (pTempIntList(size(aInstance%pIntList)))
do I = 1, size(pTempIntList)
write (*, *) i, threadID, size(aInstance%pIntList), size (pTempIntList)
pTempIntList(I) = I
end do
end subroutine IterateList
end module MyModule
program TestOpenMP_1_AllocationWithinSubroutines
use MyModule
use omp_lib
implicit none
type(MyType) :: instance
integer :: threadCount
integer :: threadId
integer :: I
!$omp parallel private (instance, threadCount, threadId, I)
threadCount = OMP_GET_NUM_THREADS()
write (*,*) 'Thread numbers are: ', threadCount
threadId = OMP_GET_THREAD_NUM()
allocate (instance%pIntList(200 + threadId))
CALL IterateList(instance)
!$omp end parallel
end program TestOpenMP_1_AllocationWithinSubroutines