当我添加if条件时,python中通过ctypes使用的C函数会变慢

2024-09-26 22:08:09 发布

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

我尝试实现一个C函数,该函数在数据集(随机生成100万个特征向量)上循环,并在每次迭代中使用给定的特征向量处理点积运算。它完成循环的速度非常快(约0.05毫秒)

c代码:

void dotProduct(double *parameters, double *feature, double *dataset)
    {
        const int FEATURE_COUNT = parameters[0];
        const int DATASET_COUNT = parameters[1];
        const double THRESHOLD = parameters[2];
        double dotProductResult;

        for (int i = 0; i < DATASET_COUNT; i++)
        {
            dotProductResult = 0.0;
            for (int j = 0; j < FEATURE_COUNT; j++)
            {
                dotProductResult += dataset[i*FEATURE_COUNT+j] * feature[j];
            }

            // if (dotProductResult > THRESHOLD)
            // {
            //     parameters[3] = i;
            // }
        }    
    }

python代码:

ND_POINTER_PARAMETERS = np.ctypeslib.ndpointer(dtype=np.float64, 
                                      ndim=1,
                                      flags="C")
ND_POINTER_FEATURE = np.ctypeslib.ndpointer(dtype=np.float64, 
                                      ndim=1,
                                      flags="C")
ND_POINTER_DATASET = np.ctypeslib.ndpointer(dtype=np.float64, 
                                      ndim=2,
                                      flags="C")
dotProductLib.dotProduct.argtypes = [ND_POINTER_PARAMETERS, ND_POINTER_FEATURE, ND_POINTER_DATASET]
    
feature = np.random.rand(512,)
dataset = np.random.rand(1000000,512)
parameters = np.array([len(feature), len(dataset), 200, -1], dtype=np.float64)

t = time()
dotProductLib.dotProduct(parameters, feature, dataset)
print("---time taken C: ",1000*(time()-t), "ms")

但是,当我添加一个if条件来检查点积的结果是否高于给定的阈值,并将向量的索引分配到给定的地址时,速度会急剧下降(~500ms),即使它从未进入if条件

同样,当我添加std::cout而不是变量赋值时也会发生同样的情况

if (dotProductResult > THRESHOLD)
{
    std::cout << dotProductResult << "\n";
}

此外,如果我添加了一个else条件,并在if中荒谬地编写了相同的语句,或者如果我分配了任何数字,它的速度不会降低

if (dotProductResult > THRESHOLD)
{
    parameters[3] = i;
}
else
{
    parameters[3] = i;
}

if (dotProductResult > THRESHOLD)
{
    parameters[3] = 123;
}

我使用-O3标志。 我做错了什么?有没有建议尽快进行这样的手术

提前谢谢


Tags: thresholdifcountnpdatasetfeatureintparameters
1条回答
网友
1楼 · 发布于 2024-09-26 22:08:09

您的原始代码非常快,因为它实际上什么都不做!编译器识别出您实际上没有使用dotProductResult,因此函数得到optimized down to literally nothing。当您取消对条件的注释时,现在使用了dotProductResult的值,因此它必须实际计算点积。如果“添加一个else条件并在if中编写相同的语句”,那么它又快了,因为编译器意识到这相当于:

void dotProduct(double *parameters, double *feature, double *dataset)
    {
        const int DATASET_COUNT = parameters[1];

        if (DATASET_COUNT > 0)
        {
            parameters[3] = DATASET_COUNT - 1;
        }
    }

这样它就可以停止工作了

相关问题 更多 >

    热门问题