使用 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

我希望这会有所帮助。

关于您的代码: 可能没问题,但我会将 sumi 设为无符号。您可以将const 添加到数组参数类型,但编译器肯定能够自行解决。 哦,我认为你应该删除那个floor。整数除法已经做到了。

【讨论】:

我尝试了几种方法,包括操作(只是出于好奇),这是迄今为止最快的一种。根据我所做的相关计算,对于 10,000 个元素,操作代码在我的机器上总共占用了大约 160-165 µs,而这个示例大约需要 50 个!如果有人能解释与不太不同的实现相比的巨大差异(在模板实例化之后),我会很高兴。 嗨 daniel,我将研究使用您的上述功能。我确实在我自己的代码上使用了您的 cmets,所有这些都运行良好,除了使总和 unsigned ,这实际上给了我奇怪的不同输出。

以上是关于使用 C++ 加速 Python的主要内容,如果未能解决你的问题,请参考以下文章

使用 C++ 加速 Python

C++ MFC 键盘加速器

使用 Qt c++ 在 Windows Surface Pro 上获取加速度计数据?

C++使用cuBLAS加速矩阵乘法运算

加速共享内存操作 C++

NVIDIA Jetson YOLOv5 tensorRT部署和加速 C++版