コンパイラはifort.
単語帳.毎回検索するのが面倒なので転載多め.元URLあり.
自前の検証メモも.
他ファイルの手続きをそのまま渡す
mymod1.f90にあるmysubという手続きをmymod2.f90でuseすると,他ファイルからはuse mymod2, only: mysub1
で使える
mymod1.f90
module mymod1
implicit none
contains
subroutine mysub1
write(*, *) 'hello'
end subroutine mysub1
end module mymod1
mysub2.f90
module mymod2
use mymod1, only: mysub1 ! only以降ははなくても可
end module mymod2
main.f90
program main
use mymod2, only: mysub1
implicit none
call mysub1 ! hello
end program main
use, only
で複数モジュールに重複した名前を定義可能
module mod10
implicit none
integer :: a = 10
end module mod10
module mod20
implicit none
integer :: a = 20
end module mod20
program main
use mod10, only: a
! use mod20, only: a
implicit none
write(*, *) a ! 10,もしmod10をコメントアウト+mod20を使うと20
end program main
使い方1
only
句で使用する変数を明示するのが良いと考えられる.
なぜなら,これを省略するとコンパイルエラー(コンパイル時に検出してくれるのでありがたい)になるが,エラーの出る箇所は書き方によって変わるからである↓↓
! パターン1
use mod10, only: a
use mod20, only: a ! ここでエラー
! パターン2
use mod10!, only: a
use mod20, only: a ! ここでエラー
! パターン3
use mod10, only: a ! ここでエラー
use mod20!, only: a
! パターン4
use mod10!, only: a
use mod20!, only: a
implicit none
write(*, *) a ! ここでエラー
使い方2
重複した変数の両方を使いたい場合,別名で参照する:
(@septcolorさんありがとうございます!)
program main
use mod10, only: a10 => a
use mod20, only: a20 => a
! use mod10, only: a10 => a, aをするとa10もaも(10として)使えるが…
implicit none
write(*, *) a10, a20 ! 10 20
! write(*, *) a ! 本来の変数名は使えない
end program main
独立した関数と構造体のメソッドの速度は変わらない
これを使うと関数・サブルーチンの階層化が可能!?
以下の例の時間計測結果:
ケース | no option [sec] | -flto [sec] | -ip [sec] | -ipo [sec] |
---|---|---|---|---|
関数を直接使用 | 5.82 | 5.81 | 5.81 | 5.86 |
構造体のメソッド使用 | 5.89 | 5.89 | 5.90 | 5.94 |
- 関数を直接使用する方が1%程度高速
- 構造体経由の方が可読性が向上するなら許容範囲?
- link-time optimization関連のコンパイルオプションによる変化は小さい
- @septcolorさんありがとうございます!
- 他のコンパイルオプションとの組み合わせ,構造体の中身が複雑化したときの速度は未検証
- 式は[Qiita@hanaata: 色々な言語で計算速度を比較してみた]
(https://qiita.com/hanaata/items/c91788bcac2a40f1bb05)を参照
module mymod
implicit none
type Funcs
contains
procedure :: mymethod => mymethod
end type Funcs
type(Funcs) :: myobj
contains
function myfunc(i) result (y) ! これが使いたい関数
integer, intent(in) :: i
real(8) :: y
y = (-1.d0) ** dble(i) * (2.d0 * dble(i) + 1.d0) ** 0.1d0
end function myfunc
function mymethod(self, i) result(y) ! 中身は上の関数と同じだが構造体経由でアクセスする用
class(Funcs), intent(in) :: self
integer, intent(in) :: i
real(8) :: y
y = (-1.d0) ** dble(i) * (2.d0 * dble(i) + 1.d0) ** 0.1d0
end function mymethod
end module mymod
program main
use mymod, only: myfunc, myobj
implicit none
integer, parameter :: n = 100, niter = 10
integer :: itime, ix, iy, i, iiter
real(8) :: a(n,n), time(niter)
integer :: t1, t2, t_rate, t_max, diff
! 関数を直接使用
time(:) = 0.d0
do iiter = 1, niter
call system_clock(t1)
do itime = 1, 10 ** 4
do iy = 1, n
do ix = 1, n
do i = 0, n
a(ix,iy) = a(ix,iy) + myfunc(i)
enddo
enddo
enddo
enddo
call system_clock(t2, t_rate, t_max)
if ( t2 < t1 ) then
diff = (t_max - t1) + t2 + 1
else
diff = t2 - t1
endif
time(iiter) = diff / dble(t_rate)
enddo
write(*, *) sum(time) / dble(niter)
! 構造体のメソッド使用
time(:) = 0.d0
do iiter = 1, niter
call system_clock(t1)
do itime = 1, 10 ** 4
do iy = 1, n
do ix = 1, n
do i = 0, n
a(ix,iy) = a(ix,iy) + myobj%mymethod(i)
enddo
enddo
enddo
enddo
call system_clock(t2, t_rate, t_max)
if ( t2 < t1 ) then
diff = (t_max - t1) + t2 + 1
else
diff = t2 - t1
endif
time(iiter) = diff / dble(t_rate)
enddo
write(*, *) sum(time) / dble(niter)
end program main