【问题标题】:Python vs Julia speed comparisonPython vs Julia 速度比较
【发布时间】:2020-08-06 19:33:37
【问题描述】:

我试图比较这两个 sn-ps,看看一秒钟可以完成多少次迭代。事实证明,Julia 实现了 250 万次迭代,而 Python 实现了 400 万次。朱莉娅不是应该更快吗?还是这两个 sn-ps 不等价?

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 是如何工作的,但看起来你必须为每次比较构建一个新对象,而 Python 正在做简单的整数比较。
  • 另外请注意,这是某种穷人的速度比较,不是吗?现在,你可以让 Python 和 Julia 以大致相同的速度运行,并且有适当的动机(在两端)。如果您这样做是为了学习任何一种语言,请查看哪种语言更容易让您思考。您可以稍后在实际需要时对其进行优化。
  • @norok2 这适用于某些代码,但不适用于其他代码。如果您能够将 Python 代码转换为对以快速语言编写的库函数的调用,或者如果它受 numba 或类似的支持,那么也许可以,但否则 Python 会慢得多。
  • @DNF 在某些方面 Python 更快,而在某些方面 Julia 更快。我相信你可以找到两者的例子。仅仅因为相对昂贵的显式循环和函数调用,说 Python “显着”(无论这意味着什么)慢,是过分忽视了整体情况。当然,如果这是你的主力,也许你和 Julia 在一起会更好。但是,如果您使用正确的工具,您可以在 Python 中获得同样快的速度。学习这些工具是否值得,还是学习另一种语言更好。很难说。
  • 我同时使用这两种语言,虽然有“一些”例子表明这两种语言都更快,但平衡是相当大的一方面。这只是 Python 被解释并且几乎不关注性能的结果,而 Julia 非常关注性能。这实际上很像说 Python 与 C 一样快。如果 没有 有显着差异,那就太奇怪了,而且会破坏 Julia 的大部分目的。

标签: python julia


【解决方案1】:

这是一种奇怪的性能比较,因为通常人们衡量的是计算实体所需的时间,而不是查看在一定时间内可以进行多少次微不足道的迭代。我无法让您的 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()

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 万次迭代。所以我猜 Julia 的循环速度更快?耶!好吧,实际上这个循环中的主要工作是对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    

哇,零秒!这怎么可能?好吧,让我们看一下LLVM code(有点像机器代码,但用于用作中间表示的假想机器),它降低到:

julia> @code_llvm h()

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

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

【讨论】:

  • 它是编程语言的BogoMips
  • 对,但是 bogomips 是用来测量 CPU 的,而不是编程语言。但可以肯定的是,这是一件可以衡量的事情。
【解决方案2】:

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

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


朱莉娅 1.4.0:

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

但请注意,简单地使用time(即比较纯数字)仍然更快:

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 中使用 time.perf_counter_ns() 吗?
  • 使用 time.perf_counter_ns 不会改变这个基准的任何东西(至少在我的系统上)。我想,在测量 1 秒左右的时间差时,时间测量的准确性并不重要。只有测量和比较结果对象所花费的时间在这里很重要(以及循环本身的效率)。
  • 在 Julia 中,测量时间很重要——这就是为什么在我的代码中我使用 time_ns 而不是 time,因为它比那时快 30%。
【解决方案3】:

您可能想在 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 倍。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-07
    • 2011-10-21
    • 1970-01-01
    • 2020-05-10
    • 2016-06-25
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多