给出一个向量加法:
NPNumber NPNumber::plus(const double o) const {
vector<double> c;
for (double a : values)
c.push_back(a + o);
return NPNumber(width, c);
}
当NPNumber包含双精度矢量(字段值)时,当我只添加一个整数而不是另一个NPNumber时,与转换该整数并使用上述函数相比,是否存在性能优势或损失?
即,在任何架构上这都更快/更慢:
NPNumber NPNumber::plus(const int i) const {
vector<double> c;
for (double a : values)
c.push_back(a + i);
return NPNumber(width, c);
}
答案 0 :(得分:4)
强烈依赖编译器,你应该在你的代码中测量它。在我的机器上进行快速简单的观察(32位MinGW / gcc 4.9)显示+
本身在两种情况下都是相同的,但积分运算看起来好一些。
添加两个double
:
! double d = 0.2;
fldl 0x409070
fstpl -0x10(%ebp)
! double y = 1.0;
fld1
fstpl -0x18(%ebp)
! double z = d + y;
fldl -0x10(%ebp)
faddl -0x18(%ebp)
fstpl -0x20(%ebp)
添加两个int
:
! double d = 0.2;
fldl 0x409070
fstpl -0x28(%ebp)
! int y = 1;
movl $0x1,-0x2c(%ebp)
! double z = d + y;
fildl -0x2c(%ebp)
faddl -0x28(%ebp)
fstpl -0x38(%ebp)
两者都使用faddl
来添加,但编译器在添加之前使用更好的指令来加载整数。因此,将一个整数添加到double中没有任何惩罚(它可能更好,而不是添加两个双精度)。
在您的应用程序中,分析是找出哪个更好的最佳方式。
答案 1 :(得分:2)
需要考虑的另一件事是编译器优化。
浮点单元往往有自己的寄存器。在某些情况下,这些甚至可能比典型的操作数具有更高的精度(例如,80位临时实数;)但是,请参阅注释,因为这可能会有很大差异。
我希望对已加载到FPU中的值进行操作会更便宜,编译器应该知道这一点。因此,它可以提升你的常量值从循环中提升并保持值加载到FPU中,在这种情况下,大矢量上的差异可以忽略不计。
无论如何,我希望如果int
到double
转换在给定平台上很昂贵,那么可敬的编译器就不会冗余地执行它。因此,我可能会做的是使它成为一种模板方法,这样你就可以接受任何类型的&amp;精度恒定数据自然来自;这允许编译器在任何给定情况下为特定平台“做正确的事情”。
话虽如此,编译器的优化策略确实有很大不同,平台的功能和功能各不相同。性能特征,所以如果你试图挤出每一个微秒,你应该对你感兴趣的平台进行分析。