优化移植到Python的C算法

2024-05-14 15:49:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我想用Python编写一个实时音频到音高算法,看起来Yin算法解决了这个问题。我已经找到了许多Yin的C实现,并且在我的语音上试用了其中一个,它可以像预期的那样实时工作。我已经开始将它移植到Python上,但我可以看到它的速度大约慢了100倍——因此不再是real.time。我使用的是2.3 GHz四核Intel Core i7

下面是用C语言和Python语言对该算法的模拟,以了解所涉及的计算。每次模拟计算90000个样本的螺距。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包装器编写C库是我唯一的选择


Tags: 代码in算法forincludetimebufferrange
2条回答

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

只需使用njit decorator并将嵌套for循环包装到函数中即可

是的,Python在许多应用程序中都比C慢得多。那些需要大量数值计算的是一些最坏的情况。解决这些问题有多种方法

直接用C编写扩展是一种老派的方式,它可能对您特别有吸引力,因为您已经有了C代码。有一些工具可以帮助实现这一点,比如swig

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

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

相关问题 更多 >

    热门问题