2017-11-12 7 views
0

私はサブルーチンとそれを呼び出すいくつかのFortranコードを持っています。定義されたウィンドウサイズを使用して行列の要素の平均を計算することになっています。たとえば、winsize = 2を使用して(10,10)配列のサブルーチンを呼び出すと、(5,5)配列が返されます。示すようにFortranの "end program"文のセグメンテーションフォルト

コードは次のとおりです。

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でデバッグしようとしましたが、驚いたことに、正しい結果を返しますが、プログラムを終了するときにはsegfaultsを返します。

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を返していますが、別の場所でフォールトしています。

誰かが問題を特定するのを手助けできますか?おかげで

答えて

3

デバッグモードでプログラムをコンパイルし、多くのデバッグスイッチをアクティブにすることができます。

私の場合は、gfortranでコンパイルされ、私が使用:

  1. -gをデバッグシンボルが含まれるように
  2. -fbacktraceより良いスタックトレースのため
  3. -Wallをすべてのコンパイラの警告
  4. -fcheck=allのを可能にするために、実行時間のチェックを有効にします(プログラムの速度を遅くしますが、デバッグ中は本当に便利です)。

これらの実行時チェックはすぐにエラーを見つけました:store

At line 21 of file teste.F 
Fortran runtime error: Array bound mismatch for dimension 1 of array 'store' (2/3) 

サイズは(winsize, winsize)ですが、サイズ(windsize+1, winsize+1)のそれへの配列をコピーします。 Fortranで配列をスライスすると、開始インデックスと終了インデックスの両方が含まれます。(1:1+10)の場合は、1から11になります。つまり、そのサイズは11です。

実行時間なし(この場合は-fcheck=allによって起動されます)これは本当にデバッグが難しく、あらゆる種類の予期しない動作を引き起こす可能性があります。

gfortran以外のコンパイラを使用する場合は、スイッチが標準化されていないため、コンパイラでこのようなテストをどのように切り替えるかをお読みください。

2

これはあなたの質問に対する回答ではありませんが(私はすでに回答しています)、あなたに役立つヒントはいくつかあります。

  1. あなたは多次元配列をループ、あなたは常に最初のインデックスを超える最も内側のループを持っている必要があり、かつ、その

    ! Inefficient way to do it: 
    do i = 1, 10 
        do j = 1, 10 
         do k = 1, 10 
          a(i, j, k) = i*j+k 
         end do 
        end do 
    end do 
    
    !Efficient way to do it: 
    do k = 1, 10     ! <-+ 
        do j = 1, 10    ! | swapped 
         do i = 1, 10   ! <-+ 
          a(i, j, k) = i*j+k 
         end do 
        end do 
    end do 
    

    方法Fortranの店舗多次元等々場合配列は、最初のインデックスが最も速く変化するものです。したがって、効率的な方法では連続した要素を読み込みますが、非効率的な方法ではメモリ内をかなりジャンプする必要があります。代わりに、この複雑なループの

  2. 、あなたは同じように簡単にSUMCOUNTを使用することができます。numbのあなたの値が同じように簡単にnumb=COUNT(store/=-99)ように計算することができるよう

    • COUNTは、配列内の.TRUE.のインスタンスをカウントし
    • SUMには、特定の値を省略するために使用できる任意の引数MASKがあります。 -99ないすべての値を合計するには、使用することができます:

    s = SUM(store, MASK=(store /= -99))だからあなただけであなたのコードの約15行を置き換えることができます:

    ave = sum(store, MASK=(store/=par))/count(store/=par) 
    
  3. 両方storepardouble precisionをしています、浮動小数点変数を絶対的な等価性のために比較することは、tricky

関連する問題