这是一种奇怪的性能比较,因为通常情况下,它会衡量计算某种物质所需的时间,而不是查看在一定时间内可以进行多少次微不足道的迭代。我无法让您的Python和Julia代码正常工作,所以我修改了Julia代码使其正常工作,只是没有运行Python代码。正如@chepner在评论中指出的那样,使用对象now()
进行时间比较并进行比较DateTime
非常昂贵。Python time.time()
函数仅返回浮点值。事实证明,有一个名为Julia的函数time()
可以执行完全相同的操作:
julia> time()
1.587648091474481e9
这是f()
我的系统上原始功能(经过修改可正常工作)的时间:
julia> using Dates
julia> function f()
i = 0
t1 = now()
while true
i += 1
if now() - t1 >= Millisecond(1000)
break
end
end
return i
end
f (generic function with 1 method)
julia> f()
4943739
在时间用完之前,它进行了将近500万次迭代。就像我说的那样,我无法让您的Python代码在没有明显摆弄的情况下在我的系统上运行(我没有打扰过)。但是这f()
是使用的一个版本time()
,我将其想象性地称为g()
:
julia> function g()
i = 0
t1 = time()
while true
i += 1
if time() - t1 >= 1
break
end
end
return i
end
g (generic function with 1 method)
julia> g()
36087637
该版本进行了3600万次迭代。所以我想朱莉娅在循环时更快?好极了!好吧,实际上,此循环中的主要工作是对time()
so 的调用。Julia生成大量time()
调用的速度更快!
为什么时间如此奇怪?正如我所说,这里的大多数实际工作都在打电话time()
。循环的其余部分实际上没有执行任何操作。在优化的编译语言中,如果编译器看到一个循环不执行任何操作,它将完全消除循环。例如:
julia> function h()
t = 0
for i = 1:100_000_000
t += i
end
return t
end
h (generic function with 1 method)
julia> h()
5000000050000000
julia> @time h()
0.000000 seconds
5000000050000000
哇,零秒!那怎么可能?好吧,让我们看一下LLVM代码(有点像机器代码,但对于用作中间表示的假想机器),它降低为:
julia> @code_llvm h()
; @ REPL[16]:1 within `h'
define i64 @julia_h_293() {
top:
; @ REPL[16]:6 within `h'
ret i64 5000000050000000
}
编译器看到了循环,发现每次的结果都是相同的,只返回该常数值而不实际执行循环。当然,这需要零时间。