Python与Julia速度比较

Python与Julia速度比较,python,julia,Python,Julia,我试着比较这两个片段,看看一秒钟可以完成多少次迭代。结果是Julia实现了250万次迭代,而Python实现了400万次迭代。朱莉娅不是应该更快吗。或者这两个片段不是等价的 Python: t1 = time.time() i = 0 while True: i += 1 if time.time() - t1 >= 1: break function f() i = 0 t1 = now() while true

我试着比较这两个片段,看看一秒钟可以完成多少次迭代。结果是Julia实现了250万次迭代,而Python实现了400万次迭代。朱莉娅不是应该更快吗。或者这两个片段不是等价的

Python:

t1 = time.time()
i = 0
while True:
    i += 1
    if time.time() - t1 >= 1:
        break
function f()
    i = 0
    t1 = now()
    while true
        i += 1
        if now() - t1 >= Base.Dates.Millisecond(1000)
            break
        end
    end
    return i
end
julia> using Dates

julia> function f()
           i = 0
           t1 = now()
           while true
               i += 1
               if now() - t1 >= Dates.Millisecond(1000)
                   break
               end
           end
           return i
       end
f (generic function with 1 method)

julia> f()
6339528
朱莉娅:

t1 = time.time()
i = 0
while True:
    i += 1
    if time.time() - t1 >= 1:
        break
function f()
    i = 0
    t1 = now()
    while true
        i += 1
        if now() - t1 >= Base.Dates.Millisecond(1000)
            break
        end
    end
    return i
end
julia> using Dates

julia> function f()
           i = 0
           t1 = now()
           while true
               i += 1
               if now() - t1 >= Dates.Millisecond(1000)
                   break
               end
           end
           return i
       end
f (generic function with 1 method)

julia> f()
6339528

您可能希望在Julia中使用
time\ns
函数:

function f()
    i = 0
    t1 = time_ns()
    while true
        i += 1
        if time_ns() - t1 >= 10^9
            break
        end
    end
    return i
end

在我的计算机上,它的运行速度比Python快10倍。

好吧,这不是我在系统上观察到的:

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
Python 3.7.7

Python 3.7.7 (default, Mar 26 2020, 15:48:22) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import time                                                                                                                                                       

In [2]: def f(): 
   ...:     t1 = time.time() 
   ...:     i = 0 
   ...:     while True: 
   ...:         i += 1 
   ...:         if time.time() - t1 >= 1: 
   ...:             return i 
   ...:                                                                                                                                                                   

In [3]: f()                                                                                                                                                               
Out[3]: 4676268

Julia 1.4.0:

t1 = time.time()
i = 0
while True:
    i += 1
    if time.time() - t1 >= 1:
        break
function f()
    i = 0
    t1 = now()
    while true
        i += 1
        if now() - t1 >= Base.Dates.Millisecond(1000)
            break
        end
    end
    return i
end
julia> using Dates

julia> function f()
           i = 0
           t1 = now()
           while true
               i += 1
               if now() - t1 >= Dates.Millisecond(1000)
                   break
               end
           end
           return i
       end
f (generic function with 1 method)

julia> f()
6339528
但请注意,简单地使用时间(即比较普通数字)仍然更快:

julia> function f()
           i = 0
           t1 = time()
           while true
               i += 1
               if time() - t1 >= 1
                   break
               end
           end
           return i
       end
f (generic function with 1 method)

julia> f()
24742703


这是一种奇怪的性能比较,因为通常情况下,我们衡量的是计算实质性内容所需的时间,而不是看一个人在一定时间内可以进行多少次琐碎的迭代。我很难让Python和Julia代码正常工作,所以我修改了Julia代码使其正常工作,只是没有运行Python代码。正如@chepner在评论中指出的,使用
now()
并与
DateTime
对象进行时间比较是相当昂贵的。Python
time.time()
函数只返回一个浮点值。事实证明,有一个名为
time()
的Julia函数,其作用与此完全相同:

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()

这个版本进行了3600万次迭代。所以我猜朱莉娅在循环方面更快?耶!实际上,这个循环的主要工作是调用
time()。。。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    
哇,零秒!这怎么可能?好的,让我们看一下(有点像机器代码,但对于用作中间表示的虚拟机器),这降低到:

julia> @code_llvm h()

;  @ REPL[16]:1 within `h'
define i64 @julia_h_293() {
top:
;  @ REPL[16]:6 within `h'
  ret i64 5000000050000000
}

编译器看到循环,发现每次的结果都是相同的,只返回那个常量值,而不是实际执行循环。当然,这需要零时间。

我不确定Julia是如何工作的,但似乎您必须为每次比较构造一个新对象,而Python正在进行简单的整数比较。另外请注意,这是某种穷人的速度比较,不是吗?现在,只要有足够的动力(在两端),就可以让Python和Julia以大致相同的速度运行。如果你这样做是为了学习这两种语言中的任何一种,那么看看哪一种更容易让你思考。您可以在以后实际需要时对其进行优化。@norok2这对某些代码是正确的,但对其他代码则不然。如果您能够将Python代码转换为对用快速语言编写的库函数的调用,或者如果它受numba或类似软件的支持,那么可能是这样,但Python的速度明显较慢。@DNF有些地方Python更快,有些地方Julia更快。我相信你可以找到这两个例子。仅仅因为显式循环和函数调用相对昂贵,就说Python“显著”(不管这意味着什么)慢了,这是过分忽略了整个情况。当然,如果这是你的工作重点,也许你和朱莉娅在一起会更好。但是,如果您使用正确的工具,那么在Python中也可以获得同样快的速度。学习这些工具值得吗?还是学习一门不同的语言更好。这很难说。我使用两种语言,虽然有“一些”两种语言都更快的例子,但平衡在很大程度上是一边的。这只是Python被解释的结果,几乎不关注性能,而Julia非常关注性能。实际上,这很像说Python和C一样快。如果没有显著的差异,那将是非常奇怪的,这将破坏Julia的许多目的。你不应该在Python中使用吗?使用time.perf_counter_ns不会改变这个基准测试的任何东西(至少在我的系统上)。我想,当测量1秒量级的时差时,时间测量的准确性并不重要。在这里,只有测量和比较结果对象所需的时间很重要(以及循环本身的效率)。在Julia中,测量时间很重要-这就是为什么在我的代码中我使用
时间
而不是
时间
,因为它比以前快了约30%。这是编程语言的优势,但是bogomips是用来测量CPU的,而不是编程语言。当然,这是可以衡量的。