为什么在存在隐式转换时赋值速度变慢?
Why is assignment slower when there's an implicit conversion?
如果有类似的问题请指导我,我安静地搜索了一段时间但没有找到任何东西。
背景:
我只是在玩耍,发现了一些我无法完全解释的行为......
对于原始类型,看起来当存在隐式转换时,与显式赋值相比,赋值运算符 = 需要更长的时间。
int iTest = 0;
long lMax = std::numeric_limits<long>::max();
for (int i=0; i< 100000; ++i)
{
// I had 3 such loops, each running 1 of the below lines.
iTest = lMax;
iTest = (int)lMax;
iTest = static_cast<int>(lMax);
}
结果是 c 风格转换和 c++ 风格 static_cast 平均执行相同(每次不同,但没有明显差异)。 AND 它们都优于隐式赋值。
Result:
iTest=-1, lMax=9223372036854775807
(iTest = lMax) used 276 microseconds
iTest=-1, lMax=9223372036854775807
(iTest = (int)lMax) used 191 microseconds
iTest=-1, lMax=9223372036854775807
(iTest = static_cast<int>(lMax)) used 187 microseconds
问题:
为什么隐式转换导致延迟较大?我可以猜到它必须在int溢出的赋值中检测到,所以调整为-1。但是作业中到底发生了什么?
谢谢!
如果你想知道幕后发生的事情的原因,最好的地方是……等等……幕后:-)
这意味着检查编译器生成的汇编语言。
最好将 C++ 环境视为 运行 C++ 代码的抽象机。该标准(大部分)规定了 行为 而不是实施细节。一旦离开 standard 的范围并开始思考下面发生的事情,C++ 源代码就不再有什么帮助了——您需要检查 actual code that the computer is 运行,编译器输出的东西(通常是机器码)。
可能是编译器放弃了循环,因为它每次都计算相同的东西,所以只需要执行一次。如果它可以确定您不使用结果,它可能会完全丢弃代码。
很久以前,VAX Fortran 编译器(我确实说过 很多 个月)在给定的基准测试中比竞争对手好几个数量级。
那是 确切 的原因。它确定没有使用循环的结果,因此优化了整个循环。
您可能需要注意的另一件事是测量工具本身。当您谈论 1/10,000th 秒的持续时间时,您的结果可能是被一点噪音淹没。
有一些方法可以减轻这些影响,例如确保您测量的对象是实质性的(例如超过 10 秒),或者使用统计方法消除任何噪音。
但最重要的是,它可能是导致您看到的结果的测量方法。
#include <limits>
int iTest = 0;
long lMax = std::numeric_limits<long>::max();
void foo1()
{
iTest = lMax;
}
void foo2()
{
iTest = (int)lMax;
}
void foo3()
{
iTest = static_cast<int>(lMax);
}
使用 -O3
使用 GCC 5 编译得到:
__Z4foo1v:
movq _lMax(%rip), %rax
movl %eax, _iTest(%rip)
ret
__Z4foo2v:
movq _lMax(%rip), %rax
movl %eax, _iTest(%rip)
ret
__Z4foo3v:
movq _lMax(%rip), %rax
movl %eax, _iTest(%rip)
ret
它们完全一样。
由于您没有提供完整的示例,我只能猜测差异是由于您没有向我们展示的内容造成的。
如果有类似的问题请指导我,我安静地搜索了一段时间但没有找到任何东西。
背景:
我只是在玩耍,发现了一些我无法完全解释的行为...... 对于原始类型,看起来当存在隐式转换时,与显式赋值相比,赋值运算符 = 需要更长的时间。
int iTest = 0;
long lMax = std::numeric_limits<long>::max();
for (int i=0; i< 100000; ++i)
{
// I had 3 such loops, each running 1 of the below lines.
iTest = lMax;
iTest = (int)lMax;
iTest = static_cast<int>(lMax);
}
结果是 c 风格转换和 c++ 风格 static_cast 平均执行相同(每次不同,但没有明显差异)。 AND 它们都优于隐式赋值。
Result:
iTest=-1, lMax=9223372036854775807
(iTest = lMax) used 276 microseconds
iTest=-1, lMax=9223372036854775807
(iTest = (int)lMax) used 191 microseconds
iTest=-1, lMax=9223372036854775807
(iTest = static_cast<int>(lMax)) used 187 microseconds
问题:
为什么隐式转换导致延迟较大?我可以猜到它必须在int溢出的赋值中检测到,所以调整为-1。但是作业中到底发生了什么?
谢谢!
如果你想知道幕后发生的事情的原因,最好的地方是……等等……幕后:-)
这意味着检查编译器生成的汇编语言。
最好将 C++ 环境视为 运行 C++ 代码的抽象机。该标准(大部分)规定了 行为 而不是实施细节。一旦离开 standard 的范围并开始思考下面发生的事情,C++ 源代码就不再有什么帮助了——您需要检查 actual code that the computer is 运行,编译器输出的东西(通常是机器码)。
可能是编译器放弃了循环,因为它每次都计算相同的东西,所以只需要执行一次。如果它可以确定您不使用结果,它可能会完全丢弃代码。
很久以前,VAX Fortran 编译器(我确实说过 很多 个月)在给定的基准测试中比竞争对手好几个数量级。
那是 确切 的原因。它确定没有使用循环的结果,因此优化了整个循环。
您可能需要注意的另一件事是测量工具本身。当您谈论 1/10,000th 秒的持续时间时,您的结果可能是被一点噪音淹没。
有一些方法可以减轻这些影响,例如确保您测量的对象是实质性的(例如超过 10 秒),或者使用统计方法消除任何噪音。
但最重要的是,它可能是导致您看到的结果的测量方法。
#include <limits>
int iTest = 0;
long lMax = std::numeric_limits<long>::max();
void foo1()
{
iTest = lMax;
}
void foo2()
{
iTest = (int)lMax;
}
void foo3()
{
iTest = static_cast<int>(lMax);
}
使用 -O3
使用 GCC 5 编译得到:
__Z4foo1v:
movq _lMax(%rip), %rax
movl %eax, _iTest(%rip)
ret
__Z4foo2v:
movq _lMax(%rip), %rax
movl %eax, _iTest(%rip)
ret
__Z4foo3v:
movq _lMax(%rip), %rax
movl %eax, _iTest(%rip)
ret
它们完全一样。
由于您没有提供完整的示例,我只能猜测差异是由于您没有向我们展示的内容造成的。