我尝试了一种算法,计算从t = 1到n的1 / t ^ 2之和(来自书Julia High Perfromance),以比较python3与julia的速度.
现在我有一些问题:
1)在我的计算中,朱莉娅没有预期的那么快? Julia ist JIT编译.它应该非常快.为什么python更快?
2)为什么python中的循环如此缓慢?
3)为什么python sum方法比numpy.sum方法慢
4)为什么python geting的sum函数与numpy.sum函数的解决方案略有不同?
我希望你能帮助我.
代码:
# Benchmark Python vs Julia# (from Julia High Performance page 7 from Avik Sengupta)import scipy as spimport time# Sum of 1/t^2 from t = 1 to n by using loops:# --------------------------------------------def pisum(w,n): u_sum = 0 for vi in range(w): u_sum = 0 for vj in range(1,n+1,1): u_sum += 1.0/(vj*vj) return u_sum# Sum of 1/t^2 from t = 1 to n by using scipy functions:# ------------------------------------------------------def pisum1(w,n): for vi in range(w): vj = sp.arange(1,1) vj = sp.multiply(vj,vj) u_sum_sp = (sp.divIDe(sp.ones(n),vj)).sum() return u_sum_sp# Sum of 1/t^2 from t = 1 to n by using scipy functions & calculating # the sum via pure python:# -------------------------------------------------------------------def pisum2(w,vj) u_sum_py = sum(sp.divIDe(sp.ones(n),vj)) return u_sum_py# Benchmarking the methods :# ========================== w = 500 n = 10000# 1) Loops:# --------- ta = time.clock()u_sum_loops = pisum(w,n)eltime_loops = time.clock() - ta# 2) scipy:# ---------ta = time.clock()u_sum_sp = pisum1(w,n)eltime_sp= time.clock() - ta# 3) scipy & sum via python:# --------------------------ta = time.clock()u_sum_py = pisum2(w,n)eltime_py= time.clock() - ta# Julia with loops:# -----------------eltime_ju_loops = 0.150857295u_sum_ju = 1.6448340718480652row_format = '{:<35} {:<5} {:<5} {:<} {:<}'print("OvervIEw calculation time:")print("-"*50)print(row_format.format("elapsed time using loops:","%.5f" % eltime_loops,"sec. (","%.2f"% (eltime_loops/eltime_ju_loops),"*time Julia)"))print(row_format.format("elapsed time using scipy:","%.5f" % eltime_sp,"%.2f"% (eltime_sp/eltime_ju_loops),"*time Julia)"))print(row_format.format("elapsed time using python:","%.5f" % eltime_py,"%.2f"% (eltime_py/eltime_ju_loops),"*time Julia)"))print(row_format.format("elapsed time using Julia and loops:","%.5f" % eltime_ju_loops,"sec.","","\n"))line1 = "sum loops:",u_sum_loopsline2 = "sum scipy:",u_sum_spline3 = "sum scipy and sum via python:",u_sum_pyline4 = "sum_julia:",u_sum_jurow_format = '{:<29} {:<18}'print("OvervIEw Sum:")print("-"*50)print(row_format.format(*line1))print(row_format.format(*line2))print(row_format.format(*line3))print(row_format.format(*line4))# Julia Code:# ===========# function pisum(w,n)# u_sum = 0;# for vi = 1:w# u_sum = 0;# for vj = 1:n# u_sum += 1.0/(vj*vj);# end# end# u_sum# end# # tic()# u_sum = pisum(500,10000)# eltime = toc()解决方法
1) In my calculations Julia is not as fast as expected? Julia ist JIT compiled. It should be very fast. Why ist python faster?
你的功能不是类型稳定的.由于它的JIT编译器,Julia并不快:因为它的类型系统它很快.它的类型系统被设计为在类型稳定函数(输出类型是输入类型的函数的函数)上使用多个调度,以在代码的每个阶段完全推导出类型,从而允许其函数基本上静态编译.通过这样做,通过将类型稳定函数链接在一起构建的函数本身可以通过类型稳定,并且与您想要编写的C / Fortran代码相比编译为1x(因为这对于所有人来说都是足够的信息)相关的编译器优化).这将在at this blog post中更详细地解释.
所以类型稳定的代码是:
function pisum(w,n) u_sum = 0.0; for vi = 1:w u_sum = 0.0; for vj = 1:n u_sum += 1.0/(vj*vj); end end u_sumend@time u_sum = pisum(500,10000)
对我而言,这个时间大约为0.02秒,比SciPy示例快2倍,比计算机上的其他实现快50倍-100倍.
请注意,您可以通过调用@code_warntype pisum(500,10000)来检查类型稳定性,这将是大写和红色突出显示返回类型不是类型稳定的行.这将向您显示您的版本将u_sum作为Int启动,然后转换为float64.想想你是否编写了一个静态编译的函数(C / Fortran):你无法编译,因为u_sum的类型是未知的.
2) Why are loops in python so slow?
因为Python中的变量是动态的.每当它命中一个变量时,解释器就需要找出变量是什么,为它找到正确的编译函数,并处理返回的值(可能进行一些转换以隐藏可能发生的真实底层变化).它本质上是一种非类型稳定的Julia函数.
3) Why is the python sum method slower than the numpy.sum method
编写NumPy假设该数组是浮点数的数组. Python数组(列表)通常是任何东西. Julia表示法是Vector {float64} vs Vector {Any}.在第一个中,您可以准确地知道类型是什么,消除类型检查,转换等.您可以知道内存中每种类型的大小是相同的,并且由于它们都是相同的,您可以将它们内联到向量,而不是让内存成为一堆指向真实对象的指针(并且指针间接禁用了许多优化).
4) Why ist the sum function of python geting a slightly different solution than the numpy.sum function?
浮点很奇怪,不是关联的. SciPy中可能存在优化,这会改变某些计算的顺序,可能是某种循环展开
故事的道德启示
通过优化代码变得快速.如果编译器有更多信息,代码可以更好地优化,因为它可以做出更好的假设并删除许多不必要的检查和间接.完全动态的Python可以给解释器/运行时几乎没有信息,迫使它通过最少优化的路径.你可以通过调用用C编写的特定参数类型函数来改善这一点,因为编译器可以优化C代码(这就是SciPy所做的).
Julia旨在允许您为编译器提供静态编译语言的完整信息,但是使用的是大多数动态语言.这是由于类型系统和多次调度.因此,在这些情况下,它能够匹配C / Fortran的编译代码,获得全速,而无需在运行时调用FFI.如果您编写的代码中编译器不能拥有任何信息,例如使输出类型随机,那么编译器就无法进行优化,代码本质上变得动态且速度与Python一样慢.这很好,因为在这些情况下C只会出现段错误…
总结以上是内存溢出为你收集整理的比较Speed Python3和Julia全部内容,希望文章能够帮你解决比较Speed Python3和Julia所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)