我尝试实现一个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
标志。
我做错了什么?有没有建议尽快进行这样的手术
提前谢谢
您的原始代码非常快,因为它实际上什么都不做!编译器识别出您实际上没有使用
dotProductResult
,因此函数得到optimized down to literally nothing。当您取消对条件的注释时,现在使用了dotProductResult
的值,因此它必须实际计算点积。如果“添加一个else
条件并在if
中编写相同的语句”,那么它又快了,因为编译器意识到这相当于:这样它就可以停止工作了
相关问题 更多 >
编程相关推荐