f2pyを使ってFortranコードをPythonで実行(ベンチマーク)
Fortranのコードをpythonに結び付けるにはf2pyツールが利用できる。そこで、f2pyを使用した場合の計算の実行速度を測定する。
- 実行手順
- テスト環境
まず、以下のFortranコードを実行する(cacl_test.f)。gfortranでコンパイル(オプションは-O3)。
c calc_test.f c program calc_test implicit none c integer i, numberIteration real*8 xValueMin, xValueMax, dxValue, xValue real*8 sum real START_TIME, END_TIME c call CPU_TIME(START_TIME) c sum = 0.0 numberIteration = 100000000 xValueMin = -10.0 xValueMax = 10.0 dxValue = (xValueMax - xValueMin)/numberIteration c do i = 1, numberIteration xValue = xValueMin + dxValue*(i-1) sum = sum + 2.5*dtanh(xValue)*dexp(-0.33*dabs(xValue)) end do write(*,*) '# ANSWER= ',sum c call CPU_TIME(END_TIME) write(*,*) '# TIME= ',END_TIME - START_TIME, ' (sec)' c stop end program calc_test
その結果は、
# ANSWER= -9.22079037357930870E-002 # TIME= 10.120632 (sec)
となる。
次にpythonだけで同じコードを書く(calc_test.py)。
# calc_test.py # from math import * import time startTime = float(time.time()) sum = 0.0 numberIteration = 100000000 xValueMin = -10.0 xValueMax = 10.0 dxValue = (xValueMax - xValueMin)/numberIteration # for i in xrange(numberIteration): xValue = xValueMin + dxValue*(i) sum += 2.5*tanh(xValue)*exp(-0.33*abs(xValue)) # print '# ANSWER= ',sum endTime = float(time.time()) print '# TIME= %f (sec)' % (endTime-startTime)
その結果は、
# ANSWER= -0.0922079112232 # TIME= 122.246774 (sec)
となる。Fortranの結果と比べて計算結果が若干異なる(小数点8位以下)のが気になるが、ここではその点は深く追求しない。
次に、pythonコードの中でforループで足し算をしていた部分だけをFortranのサブルーチンとして独立させる。次のファイルcalc_sub.fを作成する。
subroutine calc(xValueMin,xValueMax,numIter,sum) implicit none c integer i, numIter real*8 xValueMin, xValueMax, dxValue, xValue real*8 sum sum = 0.0 c dxValue = (xValueMax - xValueMin)/numIter c do i = 1, numIter xValue = xValueMin + dxValue*(i-1) sum = sum + 2.5*dtanh(xValue)*dexp(-0.33*dabs(xValue)) end do write(*,*) '# ANSWER=',sum c return end
これをモジュール化するのにコマンドf2pyを用いる。次のコマンドを実行。
$ f2py -m calc_sub -c calc_sub.f
するとcalc_sub.soが作られる。このとき特にコンパイラを指定しないが、勝手に見つけてくれてオプションも付けてくれるみたい。コンパイラを指定するときは、オプションで--fcompiler=gnuのようにする。利用可能なコンパイラのリストは以下のコマンドで確認できる。
$ f2py -c --help-fcompiler
calc_sub.soをpythonコードでimportする。コードは次のようになる(calc_sub.py)。
# calc_sub.py # from calc_sub import calc import time startTime = float(time.time()) numberIteration = 100000000 xValueMin = -10.0 xValueMax = 10.0 sum = 0.0 # calc(xValueMin, xValueMax, numberIteration, sum) # endTime = float(time.time()) print '# TIME= %f (sec)' % (endTime-startTime)
このコードを実行すると結果は、
# ANSWER= -9.22079037357930870E-002 # TIME= 10.963634 (sec)
となる。この単純な例だと当たり前の結果だが、やっぱり速い。