使用 C++ 加速 Python
Posted
技术标签:
【中文标题】使用 C++ 加速 Python【英文标题】:Speeding up Python with C++ 【发布时间】:2015-06-24 09:50:16 【问题描述】:我正在尝试通过使用 ctypes 将一些繁重的工作外包给 C++ 来加速 Python 脚本。
我已经通过一个小示例(返回 x^2)很好地启动并运行了它,但现在是时候在此配置中设置我的函数了。
我的问题是,如何在 C++ 中很好地编写 Python 代码的这个函数以确保它尽可能快,我不想仅仅因为我的 C++ 低于标准而认为我可能不会获得任何速度提升。
def shortTermEnergy(frame):
return sum( [ abs(x)**2 for x in frame ] ) / len(frame)
我将通过使用 arr = (ctypes.c_int * len(frame))(*frame)
将 frame
作为数组传递,将其从列表转换为适用于 C++ 的漂亮数组
我希望这是最佳做法,并且我没有遗漏任何明显的东西?自从我编写任何 C++ 以来,已经很长时间了。
谢谢
编辑
我暂时使用了这个 C++ 代码,如果有改进的方法,请告诉我。
#include <cmath>
extern "C" int square(int size, int array[])
int sum = 0;
for (int i = 0; i < size; i++)
int number = array[i];
int value = (number * number);
sum = sum + value;
return floor(sum / size);
其中size
是从 Python 传递的数组的 len()。
【问题讨论】:
实现取决于frame
在您的 c++ 代码(本机数组/stl 向量)中的表示方式 - 不确定效率会因一个选项而异,但有有 根据frame
的类型实现它的不同(更短/更长)方式。
我认为这将是一个原生数组(我认为这是最好的)
为什么要使用 abs(x)?平方 x 不足以获得正值吗?
很好,我会删除它。我不是该函数的原作者,因此忽略了它。
一个建议:我相信创建 python 模块 numpy 是为了加快 python 中的数学运算,在你用 C++ 重写之前尝试一下
【参考方案1】:
很抱歉没有明确回答您的问题,但我认为 numpy 解决方案会更容易实现,并且可以提高速度几乎与 C++ sn-p 一样好:
import numpy as np
frame = np.random.random_sample(10000)
def shortTermEnergy(frame):
return sum( [ abs(x)**2 for x in frame ] ) / len(frame)
>> %timeit shortTermEnergy(frame)
>> 100 loops, best of 3: 4.11 ms per loop
def dot_product(frame):
return np.dot(frame, frame)/frame.size
>> %timeit dot_product(frame):
>> 10000 loops, best of 3: 19.3 µs per loop
【讨论】:
嘿 dlenz,这实际上进行了巨大的改进,这对于如此简单的更改非常有用。 C++ 仍然按预期优于这种方法,但无论如何还是很高兴知道,干杯【参考方案2】:我会选择这个:
template<class MeanT, class AccumT = MeanT, class IterT>
MeanT mean_squares(IterT start, IterT end)
AccumT accum = 0;
for (IterT it = start; it != end; ++it)
accum += *it * *it;
return accum / (end - start);
我省略了abs
,因为它没有必要。但可能编译器能够更好地优化无符号乘法。
使用是这样的:
double result = mean_squares<double, unsigned long>(array, array + length);
// std::begin(vect), std::end(vect) in case of an STL vector
我希望这会有所帮助。
关于您的代码: 可能没问题,但我会将 sum
和 i
设为无符号。您可以将const
添加到数组参数类型,但编译器肯定能够自行解决。
哦,我认为你应该删除那个floor
。整数除法已经做到了。
【讨论】:
我尝试了几种方法,包括操作(只是出于好奇),这是迄今为止最快的一种。根据我所做的相关计算,对于 10,000 个元素,操作代码在我的机器上总共占用了大约 160-165 µs,而这个示例大约需要 50 个!如果有人能解释与不太不同的实现相比的巨大差异(在模板实例化之后),我会很高兴。 嗨 daniel,我将研究使用您的上述功能。我确实在我自己的代码上使用了您的 cmets,所有这些都运行良好,除了使总和 unsigned ,这实际上给了我奇怪的不同输出。以上是关于使用 C++ 加速 Python的主要内容,如果未能解决你的问题,请参考以下文章