这些评论和Moj的回答给出了很多很好的建议。我在使用python进行信号/图像处理方面有一些经验,而且我的头多次撞到性能墙上,我只想分享一些关于提高速度的想法。也许这些有助于用慢算法找出可能的解决方案。在
时间花在哪里了?
让我们假设你有一个很好的算法,只是太慢了。第一步是对其进行分析,看看时间花在了哪里。有时候,时间是用愚蠢的方式去做一些琐碎的事情。它可能在您自己的代码中,甚至可能在库代码中。例如,如果您想运行一个具有较大内核的2D高斯滤波器,直接卷积非常慢,甚至FFT也可能很慢。在某些情况下,用低成本的连续滑动平均值来近似滤波器可能会将速度提高10倍或100倍,并给出足够接近的结果。在
如果在某些模块/库代码中花费了大量的时间,您应该检查该算法是否只是一个缓慢的算法,或者库中是否存在一些缓慢的问题。Python对一些库来说是很好的解压,但是对于一些库来说,这是一个很好的解压,这意味着对一些库的二进制处理不是很好。另一方面,如果可以找到合适的库,在信号/图像处理中使用python的代价通常可以忽略不计。因此,用C重写整个程序通常没有多大帮助。在
有时写缓存的性能也会因C的不同而有所不同。如果数据在CPU缓存中,则可以非常快速地获取数据,如果不是,则算法速度会慢得多。这可能会根据数据大小在处理时间中引入非线性步骤。(大多数人从虚拟内存交换中知道这一点,在虚拟内存交换中,这一点更为明显。)因此,用10万点解决100个问题可能比用10万个点解决1个问题要快得多。在
要检查的一件事是计算中使用的精度。在某些情况下,float32与float64一样好,但速度更快。在许多情况下没有区别。在
多线程
Python-我有提过吗?-是一种很棒的编程语言,但它的缺点之一是它的基本形式是运行一个线程。所以,不管你的系统有多少核心,挂钟时间总是一样的。结果是其中一个核心是100%,而其他核心则在空闲时间。使事情并行并拥有多个线程可以将性能提高一倍,例如,在4核机器中。在
如果你能把问题分成几个独立的小部分,这通常是个好主意。它有助于解决许多性能瓶颈。在
也不要指望技术会来拯救。如果编写的代码不是并行的,机器很难使其并行。在
GPU
你的机器可能有一个伟大的GPU,可能有1536个数字饥饿的核心准备粉碎你扔给他们的一切。坏消息是,生成GPU代码与编写CPU代码有点不同。有一些稍微通用的api(CUDA、OpenCL),但是如果您不习惯为gpu编写并行代码,请准备一个陡峭的学习曲线。另一方面,很可能有人已经编写了您需要的库,然后您只需要钩住它。在
有了gpu,绝对的数字处理能力令人印象深刻,几乎令人恐惧。我们可以讨论3tflops(每秒3x10^12单精度浮点运算)。问题在于如何将数据传输到GPU核心,因为内存带宽将成为限制因素。这意味着,尽管在许多情况下使用gpu是一个好主意,但也有很多情况下没有收益。在
典型实际上,如果您在映像上执行许多本地操作,那么这些操作很容易并行,而且它们很适合GPU。如果你在做全球业务,情况会更复杂一些。FFT需要图像中的所有信息,因此标准算法不能很好地与gpu一起工作。(对于fft,有基于GPU的算法,它们有时会使速度更快。)
另外,要注意让你的算法在GPU上运行会把你绑定到GPU上。代码在操作系统或机器之间的可移植性受到影响。在
购买性能
另外,需要考虑的一件重要的事情是,如果您需要运行一次算法,偶尔运行一次,或者实时运行一次。有时候,解决方法就像从一台更大的计算机上争取时间一样简单。花一到两美元一小时,你就可以从拥有大量资源的快速机器上获得时间。它比你想象的更简单,而且通常更便宜。同样,GPU容量可以很容易地以类似的价格购买。在
一些云服务的一个可能稍欠宣传的特性是,在某些情况下,虚拟机的IO速度与物理机相比非常好。区别来自于这样一个事实:没有旋转盘片,每次数据寻道平均惩罚为半转。对于数据密集型应用程序,这一点可能很重要,尤其是当您处理大量文件并以非线性方式访问它们时。在