如下面的代码示例所示,主程序尝试使用OpenMP来调用子例程。在该子例程中,创建并迭代本地指针变量。该程序生成Subscript #1 of the array PTEMPINTLIST has value 208 which is greater than the upper bound of 207
个错误(具体数字不同)。我已经创建了包含用户派生类型omp-private
,但似乎调用的子例程中的局部变量也应该声明为omp-private
,但我不确定这是否属实,我不知道#39} ; t知道如何实现这一目标。
你能帮忙评论一下为什么程序会出现这样的错误吗?更重要的是,您是否可以帮助评论在使用OpenMP时如何在子例程中分配指针的最佳实践?
[root@localhost new]# ifort --version
ifort (IFORT) 12.1.0 20111011
Copyright (C) 1985-2011 Intel Corporation. All rights reserved.
[root@localhost new]# ifort test_omp.f90 -warn -check -g -trace -openmp -static
[root@localhost new]# ./a.out
Thread numbers are: 8
Thread 0 - 1
Thread 0 - 2
Thread 0 - 3
Thread 0 - 4
Thread 0 - 5
Thread 0 - 6
Thread 0 - 7
Thread 0 - 8
Thread 0 - 9
Thread 0 - 10
Thread numbers are: 8
Thread 7 - 1
Thread 7 - 2
Thread 7 - 3
Thread 7 - 4
Thread 7 - 5
Thread 7 - 6
Thread 7 - 7
Thread 7 - 8
Thread 7 - 9
Thread 7 - 10
Thread 7 - 11
Thread 7 - 12
Thread 7 - 13
Thread 7 - 14
Thread 7 - 15
Thread 7 - 16
Thread 7 - 17
Thread 7 - 18
Thread 7 - 19
Thread 7 - 20
Thread 7 - 21
Thread 7 - 22
Thread 7 - 23
Thread 7 - 24
Thread 7 - 25
Thread 7 - 26
Thread 7 - 27
Thread 7 - 28
Thread 7 - 29
Thread 7 - 30
Thread 7 - 31
Thread 7 - 32
Thread 7 - 33
Thread 7 - 34
Thread 7 - 35
Thread 7 - 36
Thread 7 - 37
Thread 7 - 38
Thread 7 - 39
Thread 7 - 40
Thread 7 - 41
Thread 7 - 42
Thread 7 - 43
Thread 7 - 44
Thread 7 - 45
Thread 7 - 46
Thread 7 - 47
Thread 7 - 48
Thread 7 - 49
Thread 7 - 50
Thread 7 - 51
Thread 7 - 52
Thread 7 - 53
Thread 7 - 54
Thread 7 - 55
Thread 7 - 56
Thread 7 - 57
Thread 7 - 58
Thread 7 - 59
Thread 7 - 60
Thread 7 - 61
Thread 7 - 62
Thread 7 - 63
Thread 7 - 64
Thread 7 - 65
Thread 7 - 66
Thread 7 - 67
Thread 7 - 68
Thread 7 - 69
Thread 7 - 70
Thread 7 - 71
Thread 7 - 72
Thread 7 - 73
Thread 7 - 74
Thread 7 - 75
Thread 7 - 76
Thread 7 - 77
Thread 7 - 78
Thread 7 - 79
Thread 7 - 80
Thread 7 - 81
Thread 7 - 82
Thread 7 - 83
Thread 7 - 84
Thread 7 - 85
Thread 7 - 86
Thread 7 - 87
Thread 7 - 88
Thread 7 - 89
Thread 7 - 90
Thread 7 - 91
Thread 7 - 92
Thread 7 - 93
Thread 7 - 94
Thread 7 - 95
Thread 7 - 96
Thread 7 - 97
Thread 7 - 98
Thread 7 - 99
Thread 7 - 100
Thread 7 - 101
Thread 7 - 102
Thread 7 - 103
Thread 7 - 104
Thread 7 - 105
Thread 7 - 106
Thread 7 - 107
Thread 7 - 108
Thread 7 - 109
Thread 7 - 110
Thread 7 - 111
Thread 7 - 112
Thread 7 - 113
Thread 7 - 114
Thread 7 - 115
Thread 7 - 116
Thread 7 - 117
Thread 7 - 118
Thread 7 - 119
Thread 7 - 120
Thread 7 - 121
Thread 7 - 122
Thread 7 - 123
Thread 7 - 124
Thread 7 - 125
Thread 7 - 126
Thread 7 - 127
Thread 7 - 128
Thread 7 - 129
Thread 7 - 130
Thread 7 - 131
Thread 7 - 132
Thread 7 - 133
Thread 7 - 134
Thread 7 - 135
Thread 7 - 136
Thread 7 - 137
Thread 7 - 138
Thread 7 - 139
Thread 7 - 140
Thread 7 - 141
Thread 7 - 142
Thread 7 - 143
Thread 7 - 144
Thread 7 - 145
Thread 7 - 146
Thread 7 - 147
Thread 7 - 148
Thread 7 - 149
Thread 7 - 150
Thread 7 - 151
Thread 7 - 152
Thread 7 - 153
Thread 7 - 154
Thread 7 - 155
Thread 7 - 156
Thread 7 - 157
Thread 7 - 158
Thread 7 - 159
Thread 7 - 160
Thread 7 - 161
Thread 7 - 162
Thread 7 - 163
Thread 7 - 164
Thread 7 - 165
Thread 7 - 166
Thread 7 - 167
Thread 7 - 168
Thread 7 - 169
Thread 7 - 170
Thread 7 - 171
Thread 7 - 172
Thread 7 - 173
Thread 7 - 174
Thread 7 - 175
Thread 7 - 176
Thread 7 - 177
Thread 7 - 178
Thread 7 - 179
Thread 7 - 180
Thread 7 - 181
Thread 7 - 182
Thread 7 - 183
Thread 7 - 184
Thread 7 - 185
Thread 7 - 186
Thread 7 - 187
Thread 7 - 188
Thread 7 - 189
Thread 7 - 190
Thread 7 - 191
Thread 7 - 192
Thread 7 - 193
Thread 7 - 194
Thread 7 - 195
Thread 7 - 196
Thread 7 - 197
Thread 7 - 198
Thread 7 - 199
Thread 7 - 200
Thread 7 - 201
Thread 7 - 202
Thread 7 - 203
Thread 7 - 204
Thread 7 - 205
Thread 7 - 206
Thread 7 - 207
forrtl: severe (408): fort: (2): Subscript #1 of the array PTEMPINTLIST has value 208 which is greater than the upper bound of 207
Image PC Routine Line Source
a.out 00000000004F0C6A Unknown Unknown Unknown
a.out 00000000004EF766 Unknown Unknown Unknown
a.out 0000000000426700 Unknown Unknown Unknown
a.out 000000000040235F Unknown Unknown Unknown
a.out 0000000000402881 Unknown Unknown Unknown
a.out 0000000000400D09 testopenmp_1_allo 39 omp.f90
a.out 00000000004006BE MAIN__ 23 omp.f90
a.out 00000000004A4CF3 Unknown Unknown Unknown
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
答案 0 :(得分:3)
使用主程序中包含的子程序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
答案 1 :(得分:2)
我认为您正在遇到变量初始化为其赋予save
属性的问题。使用空指针初始化pTempIntList
意味着它将在子例程的不同调用之间保存。我不确定实现的细节,但猜测可能是子程序的所有调用实际上都共享了这个变量的内存。
你真的应该认真考虑Anycorn的评论。使用可分配变量通常比指针更安全。如果可以使用allocatables完成,请使用它们。