【发布时间】:2022-10-23 13:52:54
【问题描述】:
我试图将 python 代码移植到 Julia 中进行尝试(下面给出了两个代码)。 Julia 在我的机器上的运行速度比 python 慢了大约 10 倍。我究竟做错了什么?我对 Julia 很陌生,所以感谢任何帮助。
这是python代码:
import matplotlib.pyplot as plt
from numba import jit
from numpy import random
import time
N=1000
kplus=2
kminus=1
T=20
T_th=10
sdt=1
frac = 0.5
threshold = frac*N
@jit(nopython=True)
def run(kp, km):
base=np.ones(N)
mb=np.arange(N)
m=N
th=0
time_data = np.zeros(int(T/sdt))
histogram=np.zeros(N+1)
time_data[0]=N
time_temp = sdt
while th<T:
if m==0:
#print(th)
break
if th>time_temp:
time_data[int(time_temp/sdt)] = m
if th>T_th:
histogram[int(m)] += 1
#time_data[int(time_temp/sdt)] = N if m>threshold else 0
time_temp = time_temp + 1*sdt
kt=m*(kp+km)
th=th+random.exponential(1/kt)
ran=kt*random.rand()
index=int(ran/(kp+km))
rem=ran-index*(kp+km)
#print(rem)
if rem<km:
base[mb[index]]=0
tmp=mb[index]
mb[index]=mb[m-1]
mb[m-1]=tmp
m=m-1
else:
pos=random.randint(N)
if base[pos]==0:
base[pos]=1
mb[m]=pos
m=m+1
return time_data, histogram
num_runs = 1000
time_data_avg = np.zeros(int(T/sdt))
td_var=np.zeros(int(T/sdt))
hist=np.zeros(N+1)
for _ in range(num_runs):
m,l = run(2,1)
hist += l
time_data_avg += m/num_runs
td_var += m*m/num_runs
td_var -= time_data_avg**2
这是我编写的相应 Julia 代码:
using Random
using Distributions
using Plots
N=1000
kplus=2
kminus=1
T=20
sdt=1
frac = 0.5
threshold = frac*N
function run(kp,km)
base=fill(1,N)
mb=collect(1:N)
m=N
th=0
time_data = fill(0,floor(Int, T/sdt))
time_data[1]=N
time_temp = sdt
while th<T
# println(th, ' ', m)
if m==0
println(th)
break
end
if th>time_temp
time_data[ceil(Int, time_temp/sdt)+1]=m
time_temp += sdt
end
kt=m*(kp+km)
th=th+rand(Exponential(1/kt))
ran=kt*rand(Float64)
index=floor(Int,ran/(kp+km))
rem=ran-index*(kp+km)
index=index+1
if rem<km
base[mb[index]]=0
tmp=mb[index]
mb[index]=mb[m]
mb[m]=tmp
m=m-1
else
pos=rand(1:N)
if base[pos]==0
base[pos]=1
mb[m+1]=pos
m=m+1
end
end
end
return time_data
end
function sample(num_runs)
time_data_avg = fill(0.0, floor(Int, T/sdt))
td_var=fill(0.0, floor(Int, T/sdt))
for i in 1:num_runs
m = run(2,1)
time_data_avg .+= m/num_runs
td_var .+= m.*(m/num_runs)
end
td_var .-= time_data_avg.^2
return time_data_avg, td_var
end
@time begin
tm,tv=sample(1000)
end
对于 python 代码,我使用 bash time 命令测量时间。我还确保 numba 没有并行化。
【问题讨论】:
-
您正在将 numba Python 代码与“vanilla”Julia 代码进行比较。这不是一个公平的比较。
-
@KlausD,我不同意。 Numba 和 Julia 都使用 jit 编译。这种比较比 Julia 与普通 Python 更加公平和有趣。无论如何,这不是比赛。 OP 只想知道为什么他们的 Julia 表现低于预期。
-
@codeenjoyer,你应该阅读 Julia 性能提示:docs.julialang.org/en/v1/manual/performance-tips 最重要的提示是避免使用全局变量,至少如果它们不是
const -
请注意,您在 Julia 代码中测量的是编译时间。如果例如代码运行 100 毫秒,编译需要 2 秒,这可能不是您想要的。运行@time 两次并使用 BenchmarkTools 进行第二次测量。其次,第 4-10 行中的所有参数都应该作为参数传递给函数。