5

単純なプログラム(実数と倍精度の両方を使用)で精度を混合し、BLASのddotルーチンを使用しようとすると、倍精度のピースの出力が正しくなくなります。コードは次のとおりです。

program test

!! adding this statement narrowed the issue down to ddot being considered real(4)
implicit none

integer, parameter :: dp = kind(1.0d0)

!! The following 2 lines were added for the calls to the BLAS routines.
!! This fixed the issue.
real(dp), external :: ddot
real, external :: sdot

real, dimension(3) :: a,b
real(dp), dimension(3) :: d,e

integer :: i

do i = 1,3
    a(i) = 1.0*i
    b(i) = 3.5*i
    d(i) = 1.0d0*i
    e(i) = 3.5d0*i
end do

write (*,200) "sdot real(4) = ", sdot(3,a,1,b,1)  ! should work and return 49.0
write (*,200) "ddot real(4) = ", ddot(3,a,1,b,1)  ! should not work

write (*,200) "sdot real(8) = ", sdot(3,d,1,e,1)  ! should not work
write (*,200) "ddot real(8) = ", ddot(3,d,1,e,1)  ! should work and return 49.0

200 format(a,f5.2)

end program test

次のように、MKLBLASライブラリを使用してgfortranとifortの両方でコンパイルしてみました。

ifort -lmkl_intel_lp64 -lmkl_sequential -lmkl_core

gfortran -lmkl_intel_lp64 -lmkl_sequential -lmkl_core main.f90

出力は次のとおりです。

sdot real(4) = 49.00
ddot real(4) =  0.00
sdot real(8) =  4.10
ddot real(8) =  0.00

倍精度値を正しく処理するようにddotルーチンを取得するにはどうすればよいですか?

さらに、-autodoubleフラグ(ifort)または-fdefault-real-8(gfortran)フラグを追加すると、両方のddotルーチンが機能しますが、sdotルーチンは失敗します。

編集: 暗黙のnoneステートメントと、ddot関数とsdot関数の2つのタイプステートメントを追加しました。関数呼び出しに指定された型がない場合、ddotは単精度実数として暗黙的に型指定されていました。

4

2 に答える 2

6

私はMKLを使用していませんが、コンパイラが関数へのインターフェイスを認識できるように、「use」ステートメントが必要な場合がありますか?または、関数を宣言します。それらは宣言されていないため、コンパイラはおそらくddotの戻りが単精度であり、ビットを誤って解釈していると想定しています。

警告オプションをオンにすると、コンパイラは問題について通知します。gfortranを使用して、次のことを試してください。

于 2011-05-08T06:04:02.703 に答える
2

誤った種類の変数を渡すことは、インターフェイスの不一致の場合です(これは違法であるため、原則として、コンパイラはWW IIIの開始を含むすべてのことを行う可能性があります)。したがって、これはスタックを混乱させ、後続の呼び出しも誤った結果を返します。それらの誤った呼び出し(「機能しないはずです」とマークされた行)をコメントアウトして、それが役立つかどうかを確認してください。

また、たとえばMSBによるgfortranの回答のように、見つけることができるすべての種類のデバッグオプションを有効にします。

于 2011-05-08T06:27:21.237 に答える