【问题标题】:Optimising a C Algorithm having ported to Python优化移植到 Python 的 C 算法
【发布时间】:2020-09-17 13:38:23
【问题描述】:

我想用 Python 写一个 Real-time Audio to Pitch 算法,看起来 Yin 算法解决了这个问题。我找到了许多 Yin 的 C 实现,并且在我的声音中尝试了其中一个,它可以按预期实时工作。我已经开始将它移植到 Python,但我可以看到它慢了大约 100 倍 - 所以不再是实时的。我使用的是 2.3 GHz 四核 Intel Core i7。

下面是用 C 和 Python 对算法进行的模拟,以了解所涉及的计算。每个模拟计算 90,000 个样本的音高。 C 函数需要 2 秒,Python 需要 200 秒才能完成。

C 代码

#include <stdio.h>
#include <stdint.h>
#include <time.h>

int main(int argc, char** argv) {
    int buffer_length = 150;
    float sec = 0;
    float* buffer = malloc(sizeof(float)*buffer_length);
    
    clock_t before = clock();

    int j;
    int16_t tau;
    int16_t i;
    float delta;
    
    for(j = 0; j < 90000; j++){
        for(tau = 0 ; tau < 75; tau++){
            for(i = 0; i < 75; i++){
                delta = buffer[i] - buffer[i + tau];
                buffer[tau] += delta * delta;
            }
        }    
    }
    
    clock_t difference = clock() - before;
    sec = difference / (float )CLOCKS_PER_SEC;
    printf("%f\n",sec);
    
    return 0;
}

Python 代码

import time

buffer = [0.0]*150

ts = time.time()

for j in range(90000):
    for tau in range(75):
        for i in range(75):
            delta = buffer[i] - buffer[i + tau]
            buffer[tau] += delta * delta

print(time.time()-ts)

我正在考虑使用 8KHz 的采样率,但如果可能的话,可能会使用更高的采样率。是否有可能大大提高 Python 代码的性能,如果可以,我将如何去做?如果没有,那么我想用 Python Wrapper 编写 C 库是我唯一的选择。

【问题讨论】:

    标签: python c optimization signal-processing


    【解决方案1】:

    这看起来像是numba 的工作。问题是python for 循环明显比 C 循环慢。使用 numba 您应该能够大大加快它们的速度,因为您自己编写了它们并且没有外部依赖项(已知会与 numba 混淆)。

    只需使用 njit 装饰器并将嵌套的 for 循环包装在一个函数中。

    【讨论】:

    • 我将所有内容都封装在一个函数中,在我的笔记本电脑上执行大约需要 88 秒。然后我用numba.njit装饰它,花了2.27秒。非常好!
    • @MattDMo 是的,这是一个惊人的区别!
    【解决方案2】:

    是的,对于许多应用程序来说,Python 比 C 慢得多。那些需要大量数值计算的情况是最坏的情况。有多种方法可以解决此类问题。

    直接用 C 编写扩展是老派的方式,它可能对您特别有吸引力,因为您已经拥有 C 代码。有一些工具可以帮助解决这个问题,例如 swig。

    或者,您可以使用 Numpy 很好地表达所需的计算。或者有 Cython,用于编写算法的一个版本或用于包装它的 C 实现。

    您要做的关键是避免在本机和 Python 数字表示之间进行转换。保留所有数字。

    【讨论】:

    • 我开始用 C 编程,但已经很久了。由于没有大量的代码要移植,我将首先尝试 numba 方法,看看我是如何进行的。
    猜你喜欢
    • 1970-01-01
    • 2021-06-29
    • 2023-03-08
    • 2015-02-21
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 2022-09-23
    • 2015-10-25
    相关资源
    最近更新 更多