我有一些Fortran代码包含一个子程序和一个调用它。 它应该使用定义的窗口大小计算矩阵中元素的平均值。 例如,使用winsize = 2在(10,10)数组上调用子例程将返回(5,5)数组。
代码如下所示:
SUBROUTINE avgwin(ts, sizelat,sizelon,winsize,size2,size3,ts_new) implicit none double precision, dimension(10,sizelat,sizelon) :: ts double precision, dimension(winsize,winsize) :: store double precision, dimension(10,size2,size3) :: ts_new double precision :: par,ave integer :: sizelat, sizelon,i,j,k,winsize,size2,size3 integer :: A, B,p,m,numb A=0 B=0 par = 11 !Hypothetical value to be excluded do i=1,10 !Looping through time do j=1,sizelat !Looping through latitude if ((j+winsize) > sizelat) then !Checks if it will exceed bounds exit !If it'll exceed, discard remaining cells end if do k=1,sizelon !Looping through longitude if ((k+winsize)>sizelon) then exit end if store = ts(i,j:j+winsize,k:k+winsize) !Gets the values for that window where (store == par) store = -99 !Replaces masked with -99 ave = 0 numb = 0 !Variable to count do p=1,winsize do m=1,winsize if (store(p,m)==-99) then !Evaluates if it's masked, i.e., =-99 ave = ave else ave = ave + store(p,m) !Sum of existent values numb = numb +1 !Updates counting variable end if end do end do ave = ave/numb !Calculates the mean ts_new(i,A,B) = ave B=B+1 end do B=0 A=A+1 end do A=0 B=0 end do END SUBROUTINE program testefor implicit none double precision, dimension(10,10,10) :: teste double precision, dimension(10,5,5) :: oi integer :: i,j,k do i=1,10 do j=1,10 do k=1,10 teste(i,j,k)=i end do end do end do CALL avgwin(teste,10,10,2,5,5,oi) print*, oi(1,5,5) end program testefor但是,当我运行它时,我会遇到分段错误。 我尝试用GDB调试它,令我惊讶的是,它返回一个正确的结果,但退出程序时会出现段错误。 我从gdb得到的可以在下面找到:
Breakpoint 1, testefor () at testefor.f90:56 56 do i=1,10 (gdb) cont Continuing. 1.0000000000000000 Program received signal SIGSEGV, Segmentation fault. 0x0000000000400f73 in testefor () at testefor.f90:67 67 end program testefor所以程序返回正确的(1,5,5)元素= 1.0,但在其他地方出错。
有人可以帮我识别问题吗? 谢谢
I have some Fortran code consisting of a subroutine and a call to it. It's supposed to calculate the mean of the elements in a matrix using a defined window size. For example, calling the subroutine on a (10,10) array using winsize=2 would return a (5,5) array.
The code is as shown:
SUBROUTINE avgwin(ts, sizelat,sizelon,winsize,size2,size3,ts_new) implicit none double precision, dimension(10,sizelat,sizelon) :: ts double precision, dimension(winsize,winsize) :: store double precision, dimension(10,size2,size3) :: ts_new double precision :: par,ave integer :: sizelat, sizelon,i,j,k,winsize,size2,size3 integer :: A, B,p,m,numb A=0 B=0 par = 11 !Hypothetical value to be excluded do i=1,10 !Looping through time do j=1,sizelat !Looping through latitude if ((j+winsize) > sizelat) then !Checks if it will exceed bounds exit !If it'll exceed, discard remaining cells end if do k=1,sizelon !Looping through longitude if ((k+winsize)>sizelon) then exit end if store = ts(i,j:j+winsize,k:k+winsize) !Gets the values for that window where (store == par) store = -99 !Replaces masked with -99 ave = 0 numb = 0 !Variable to count do p=1,winsize do m=1,winsize if (store(p,m)==-99) then !Evaluates if it's masked, i.e., =-99 ave = ave else ave = ave + store(p,m) !Sum of existent values numb = numb +1 !Updates counting variable end if end do end do ave = ave/numb !Calculates the mean ts_new(i,A,B) = ave B=B+1 end do B=0 A=A+1 end do A=0 B=0 end do END SUBROUTINE program testefor implicit none double precision, dimension(10,10,10) :: teste double precision, dimension(10,5,5) :: oi integer :: i,j,k do i=1,10 do j=1,10 do k=1,10 teste(i,j,k)=i end do end do end do CALL avgwin(teste,10,10,2,5,5,oi) print*, oi(1,5,5) end program testeforWhen I'm running it, however, I get a Segmentation Fault. I tried debugging it with GDB and, to my surprise, it returns a correct result but segfaults when exiting the program. What I get from gdb can be found below:
Breakpoint 1, testefor () at testefor.f90:56 56 do i=1,10 (gdb) cont Continuing. 1.0000000000000000 Program received signal SIGSEGV, Segmentation fault. 0x0000000000400f73 in testefor () at testefor.f90:67 67 end program testeforSo the program is returning the correct (1,5,5) element = 1.0 but faulting somewhere else.
Can someone help me identify the problem? Thanks
最满意答案
有一点可以帮助的是在调试模式下编译程序,并激活许多调试开关。
在我的情况下,我用gfortran编译,我使用:
-g包含调试符号 -fbacktrace用于更好的堆栈跟踪 -Wall启用所有编译器警告 -fcheck=all以启用运行时检查(使程序变慢,但在调试期间非常有用)。这些运行时检查立即发现错误:
At line 21 of file teste.F Fortran runtime error: Array bound mismatch for dimension 1 of array 'store' (2/3)store的大小是(winsize, winsize)但你将一个数组复制到它的大小(windsize+1, winsize+1) 。 如果在Fortran中对数组进行切片,则它包括开始和结束索引: (1:10)从1到10.如果你有(1:1+10)它从1到11,这意味着它的大小是11。
如果没有运行时数组边界检查(在这种情况下由-fcheck=all激活),这实际上很难调试,并且可能导致各种意外行为。
如果使用与gfortran不同的编译器,则需要了解如何在编译器上打开此类测试,因为交换机未标准化。
One thing that can help is to compile the program in debug mode, and activate many debug switches.
In my case I compiled with gfortran, and I used:
-g to include debug symbols -fbacktrace for a better stack trace -Wall to enable all compiler warnings -fcheck=all to enable run time checks (make the program slower, but are really useful during debugging).These runtime checks found the error immediately:
At line 21 of file teste.F Fortran runtime error: Array bound mismatch for dimension 1 of array 'store' (2/3)The size of store is (winsize, winsize) but you copy an array into it of size (windsize+1, winsize+1). If you slice an array in Fortran, it includes both the start and end index: (1:10) is from 1 to 10. If you have (1:1+10) it goes from 1 to 11, which means that its size is 11.
Without run time array bounds checks (in this case activated by -fcheck=all) this is really hard to debug and can cause all sorts of unexpected behaviour.
If you use a different compiler than gfortran, you need to read up on how to switch on such tests on your compiler, as the switches are not standardised.
更多推荐
发布评论