如何加速在强大机器上运行的Python代码?

2 投票
2 回答
7420 浏览
提问于 2025-04-18 10:21

我写了一个多分类的算法,使用了增强分类器。其中一个主要的计算是加权最小二乘回归。

  • 我用到的主要库包括:
  • statsmodels(用于回归)
  • numpy(几乎到处都用)
  • scikit-image(用于提取图像的HoG特征)

我是在Python中开发这个算法的,使用的是Anaconda的Spyder工具。

现在我需要用这个算法开始训练分类模型。我将大约传入7000到10000张图像,每张图像的大小大约是50x100,都是灰度图。

现在有人告诉我有一台强大的机器可以加快训练过程。他们问我“你在用GPU吗?”还有其他一些问题。

老实说,我对CUDA/GPU等没有经验,只是听说过。我写代码的时候并没有考虑这些。实际上,我曾天真地认为一台好机器会比普通机器自动更快地运行我的代码,而我不需要做任何额外的事情。(当然,写代码时要注意循环、O(n)等效率问题)。

那么,我的代码是否仍然可以因为在高性能计算机上运行而加速?还是说我需要修改代码才能利用并行处理的机器?

2 个回答

4

我担心光靠在一台强大的电脑上运行程序是无法加速你的程序的。我之前也遇到过这个问题。我最开始用的是Python(速度很慢),然后换成了C(也慢),最后不得不使用一些其他的技巧和方法。比如,有时候可以通过降维来加速处理,同时还能保持结果的合理准确性,或者像你提到的,使用多进程技术。

因为你在处理图像处理的问题,所以你会进行很多矩阵运算,使用GPU肯定会大有帮助。在Python中有一些不错且活跃的CUDA封装,你可以很容易地使用它们,而不需要对CUDA了解太多。我尝试过Theano、pycuda和scikit-cuda(之后应该还有更多的选择)。

7

评论和Moj的回答提供了很多好的建议。我在用Python进行信号和图像处理方面有一些经验,也曾多次碰到性能瓶颈。今天我想分享一些关于如何让程序运行得更快的想法,希望能帮助你找到解决慢算法问题的方法。

时间花在哪里了?

假设你有一个很棒的算法,但它运行得太慢。第一步就是分析一下,看看时间都花在哪里了。有时候,时间花在一些简单的事情上,可能是你自己的代码问题,也可能是库的代码问题。例如,如果你想用一个比较大的内核来运行2D高斯滤波,直接卷积会非常慢,甚至快速傅里叶变换(FFT)也可能慢。在某些情况下,用计算量小的连续滑动平均来近似滤波器,可能会让速度提高10倍甚至100倍,而且结果也差不多。

如果你发现很多时间都花在某个模块或库的代码上,你需要检查一下,是算法本身慢,还是库的某些部分慢。Python是个很棒的编程语言,但在纯数字计算方面表现不佳,这意味着大多数优秀的库都有一些二进制库来处理繁重的计算。另一方面,如果你能找到合适的库,使用Python进行信号或图像处理的性能损失通常是微不足道的。因此,完全用C重写程序通常帮助不大。

即使在C语言中,写出一个好的算法也并不简单,有时候性能会因为CPU缓存等因素而有很大差异。如果数据在CPU缓存中,就能非常快速地获取;如果不在,算法就会慢很多。这可能导致处理时间的非线性变化,具体取决于数据大小。(大多数人都知道虚拟内存交换的情况,这种差异更明显。)因此,解决100个包含100,000个点的问题,可能比解决一个包含10,000,000个点的问题要快。

另一个需要检查的点是计算中使用的精度。在某些情况下,float32的精度和float64一样好,但速度更快。在很多情况下,二者没有区别。

多线程

Python——我提到过吗?——是个很棒的编程语言,但它的一个缺点是基本形式下只能运行一个线程。因此,无论你的系统有多少个核心,实际的运行时间总是一样的。结果就是一个核心在100%使用,而其他核心则处于空闲状态。如果能将问题拆分成小的独立部分,使用多线程可能会让你的性能提高,比如在一个4核的机器上提高3倍。

通常,如果你能将问题分解成小的独立部分,这样做是个很好的主意,有助于解决许多性能瓶颈。

而且,不要指望技术会来拯救你。如果代码没有被设计成可以并行处理,机器很难让它并行。

GPU

你的机器可能有一个很强大的GPU,里面有1536个渴望计算的核心,随时准备处理你给它的任务。坏消息是,编写GPU代码和编写CPU代码有点不同。虽然有一些通用的API(如CUDA、OpenCL),但如果你不习惯为GPU编写并行代码,准备好迎接陡峭的学习曲线。另一方面,可能已经有人为你需要的功能写好了库,这样你只需连接到那个库即可。

GPU的计算能力非常强大,几乎让人感到害怕。我们可能谈论的是3 TFLOPS(每秒3万亿次单精度浮点运算)。问题在于如何将数据传输到GPU核心,因为内存带宽将成为限制因素。这意味着虽然在很多情况下使用GPU是个好主意,但也有很多情况下并没有收益。

通常,如果你在图像上执行大量局部操作,这些操作很容易并行化,适合GPU。如果你在进行全局操作,情况就复杂一些。FFT需要从整个图像获取信息,因此标准算法在GPU上效果不好。(不过也有基于GPU的FFT算法,有时能让速度大幅提升。)

另外,要注意的是,让你的算法在GPU上运行会让你绑定于那个GPU。你的代码在不同操作系统或机器上的可移植性会受到影响。

购买一些性能

还有一个重要的考虑因素是,你需要一次性运行算法,偶尔运行,还是实时运行。有时候,解决方案就是从更强大的计算机上“购买”时间。花一两美元每小时,你就可以租用到相当快的机器,资源也很丰富。这比你想象的要简单,而且通常更便宜。此外,GPU的计算能力也可以以类似的价格租用。

一些云服务的一个可能不太被宣传的特点是,在某些情况下,虚拟机的IO速度与物理机器相比非常好。这是因为虚拟机没有旋转盘片,数据寻址的平均延迟只有半个转动的时间。这在数据密集型应用中可能很重要,尤其是当你处理大量文件并以非线性方式访问它们时。

撰写回答