使用Nuba加快Python计算速度

2022-02-20 17:57:12

Python是一种速度较慢的语言,因此最好将计算委托给用更快的语言编写的代码。您可以使用现有的库(如NumPy和SciPy)来实现这一点,但是当您需要实现一个新算法,并且不想用较低级别的语言编写代码时,会发生什么呢?

对于某些类型的计算,尤其是以数组为中心的代码,Numba库可以显著加快代码的速度。有时候你需要稍微调整一下,有时候它只会在没有任何改变的情况下工作。当它工作时,它是一个非常透明的速度修正。

Numba在高层的工作方式,以及对代码运行方式的影响。

假设你有一个非常大的数组,你想计算单调递增的版本:值可以上升,但永远不会下降。例如:

[ 1 , 2 , 1 , 3 , 3 , 5 , 4 , 6 ] → [ 1 , 2 , 2 , 3 , 3 , 5 , 5 , 6 ]

def单调递增(a):范围内i的最大值=0(len(a)):如果a[i]>;max_value:max_value=a[i]a[i]=max_value

不过有个问题。NumPy速度很快,因为它可以在不调用Python的情况下完成所有计算。由于该函数涉及Python中的循环,因此我们失去了使用NumPy的所有性能优势。

对于一个10000000条目的NumPy数组,这个函数在我的计算机上运行需要2.5秒。我们能做得更好吗?

Numba是Python的即时编译器,专门关注在NumPy数组上循环运行的代码。正是我们需要的!

从numba import njit@njit def单调递增(a):范围内i的最大值=0(len(a)):如果a[i]>;max_value:max_value=a[i]a[i]=max_value

它的运行时间为0.19秒,大约快13倍;重复使用相同的代码也不错!

当然,事实证明NumPy已经有了一个功能,可以实现这一点,NumPy。最大限度积累使用这个方法,跑步只需要0.03秒。

当你能找到一个NumPy或SciPy函数来做你想做的事情时,问题就解决了。但是如果numpy呢。最大限度你不存在吗?在这一点上,如果你想要一个快速的结果,另一个选择是编写一些低级代码,但这意味着转换编程语言,一个更复杂的构建系统,以及更复杂的总体情况。

在普通的Python和更快的编译版本中,从普通的解释器运行时内部运行相同的代码。

Numba解析代码,然后根据输入以实时方式编译代码。例如,根据输入是u64数组还是浮点数组,您将获得不同版本的代码。

Numba还可以针对CPU以外的运行时;例如,您可以在GPU上运行代码。此外,上面的例子只是Numba最简单的使用模式;文档中还介绍了更多功能。

第一次调用用Numba修饰的函数时,它需要生成适当的机器代码,这可能需要一些时间。例如,我们可以使用IPython的%time命令来测量运行Numba修饰函数所需的时间:

[1]:来自numba import njit[2]:@njit…:def add(a,b):a+b在[3]:%时间add(1,2)CPU时间:用户320毫秒,系统117毫秒,总计:437毫秒墙壁时间:207毫秒在[4]:%时间add(1,2)CPU时间:用户17微秒,系统0纳秒,总计:17微秒墙壁时间:24.3微秒在[5]:%时间add(1,2)CPU时间:用户8微秒,系统:2微秒,总计:10微秒壁时间:13.6微秒

第一次调用非常慢(毫秒而不是微秒),因为它需要编译代码;之后,它运行得很快。

这是每种投入的一次性成本。例如,如果我们通过浮动,我们将不得不再次支付:

在[8]:%时间添加(1.5,2.5)CPU时间:用户40.3毫秒,系统:1.14毫秒,总计:41.5毫秒墙壁时间:41毫秒在[9]:%时间添加(1.5,2.5)CPU时间:用户16微秒,系统:3微秒,总计:19微秒墙壁时间:26微秒

没有理由使用Numba来添加两个数字,但鉴于函数的作用非常小,这很好地说明了不可避免的一次性编译开销。

Numba重新实现了Python的一个子集和NumPy API的一个子集。这会导致潜在的问题:

有些功能在Python语言和NumPy API中都不受支持。

此外,当Numba未能编译某些代码时,我的经验是,错误消息往往很难理解。

如果您可以专门使用fast NumPy或Scipy API,那么就可以用Python编写代码,并获得低级编译语言的优势和速度。在Python中,有时需要恢复为慢速for循环,这将失去很多性能优势。

你可以直接用低级语言编写代码;这意味着您可以优化所有代码路径,但现在您将使用另一种语言。

有了Nuba,您可以从常规Python中快速获得循环代码,但您只能使用有限的语言特性和NumPy API。

Numba最棒的一点就是它很容易尝试。所以,每当你有一个慢循环做一些数学,给麻巴一个旋转;如果运气好的话,它只需要两行代码就可以加快速度。

用于生产的Docker包装非常复杂,有多达70多个最佳实践需要纠正。你需要小的图像、快速的构建,以及Python应用程序的安全运行。

通过使用Python on Docker生产手册,快速学习最佳实践。

注册我的时事通讯,加入4900多名Python开发人员和数据科学家的行列,学习实用工具和技术,从Docker打包到测试,再到Python最佳实践,每周在你的收件箱中免费发布一篇新文章。