はじめに
前回の記事の最後でお知らせしていたPython(Numba)とFortranとの比較になります。またCythonについては、前回の記事のコメント欄で@SatoshiTerasakiさんにやって頂いたので参考にして下さい。
注意
私のプログラミング歴は5年程ですが、Pythonは1年、Juliaは先週から、Fortranは片手間程度というレベルです。プログラミング言語間の実行時間を、正確に検証出来るレベルではないですので、参考程度にして下さい。また間違い等あればコメント頂けると助かります。
結果(参考)
N = 100000000(1億)
Time [s] | |
---|---|
Python(TopLevel) | 44.55 |
Python(Function) | 35.52 |
Python(Numba) | 0.64 |
Julia(TopLevel) | 29.84 |
Julia(Function) | 0.33 |
Julia(inbounds) | 0.17 |
Fortran | 0.32 |
Fortran(-O3) | 0.14 |
N = 1000000000(10億)
(3回実行した中央値)
Time [s] | |
---|---|
Python(Numba) | 6.64 |
Julia(Function) | 4.13 |
Julia(inbounds) | 2.45 |
Fortran | 4.03 |
Fortran(-O3) | 2.34 |
環境
PC : MacBook Pro (Retina, 15-inch, Early 2013)
OS : macOS (x86_64-apple-darwin14.5.0)
CPU : Intel Core i7-3740QM @ 2.7 GHz
Memory : 16 GB 1600 MHz DDR3
Julia : 0.6.2
Python : 3.6.3
numpy : 1.13.3
gfortran : GNU Fortran (Homebrew GCC 7.1.0) 7.1.0
Python(TopLevel)
前回の記事で使用したコードです。
import numpy as np
import time
# 点数
N = 100000000
# 刻み
h = 0.00000004
# 初期化
y = np.zeros(N)
# 初期値
y[0] = 1
# 数値計算
start = time.time()
for n in range(N-1):
y[n+1] = (1-h)*y[n]
elapsed_time = time.time() - start
print("Elapsed Time(Python): %.2f [s]" % elapsed_time)
Python(Function)
Python(TopLevel)を関数化したコードです。
import numpy as np
import time
def main():
# 点数
N = 100000000
# 刻み
h = 0.00000004
# 初期化
y = np.zeros(N)
# 初期値
y[0] = 1
# 数値計算
start = time.time()
for n in range(N-1):
y[n+1] = (1-h)*y[n]
elapsed_time = time.time() - start
print("Elapsed Time(Python): %.2f [s]" % elapsed_time)
main()
Python(Numba)
Python(Function)に@jitデコレータをつけただけです。
下記の記事を参考に引数化して型指定も試しましたが、間違いがあるのかあまり変わらなかったです。
Python高速化 Numba入門 その2
import numpy as np
import time
from numba import jit
@jit
def main():
# 点数
N = 100000000
# 刻み
h = 0.00000004
# 初期化
y = np.zeros(N)
# 初期値
y[0] = 1
# 数値計算
start = time.time()
for n in range(N-1):
y[n+1] = (1-h)*y[n]
elapsed_time = time.time() - start
print("Elapsed Time(Python): %.2f [s]" % elapsed_time)
main()
Julia(TopLevel)
前回の記事で使用したコードです。
# 点数
N = 100000000
# 刻み
h = 0.00000004
# 初期化
y = zeros(N)
# 初期値
y[1] = 1
# 数値計算
@time for n = 1:N-1
y[n+1] = (1-h)y[n]
end
Julia(Function)
前回の記事で使用したコードです。
(修正 : 2018/1/9 18:11)
@inboundsがついていたので修正、コメント欄で@nakano_tomofumiさんに指摘して頂きました。
function main()
# 点数
N = 100000000
# 刻み
h = 0.00000004
# 初期化
y = zeros(N)
# 初期値
y[1] = 1
# 数値計算
@time for n = 1:N-1
y[n+1] = (1-h)y[n]
end
end
main()
Julia(Inbounds)
Julia(Function)に@inboundsマクロを追加したコードです。
function main()
# 点数
N = 100000000
# 刻み
h = 0.00000004
# 初期化
y = zeros(N)
# 初期値
y[1] = 1
# 数値計算
@time @inbounds for n = 1:N-1
y[n+1] = (1-h)y[n]
end
end
main()
Fortran
Fortranは色々試行錯誤した結果下記のコードで行いました。
program ODE
call main()
contains
subroutine main()
implicit none
integer, parameter :: n = 100000000
real(8) :: y(n)
real(8) h, elapsed_time
integer i
integer ti, tf, tr
! 刻み
h = 0.00000004d0
! 初期化
y = 0
! 初期値
y(1) = 1.0d0
! 数値計算
call system_clock(ti)
do i = 1,n-1
y(i+1) = (1 - h) * y(i)
end do
call system_clock(tf,tr)
elapsed_time = (tf-ti) / dble(tr)
print "('Elapsed Time(Fortran):',f8.4,'[s]')", elapsed_time
end subroutine
end program ODE