float与int比较所需的额外时间
Is extra time required for float vs int comparisons?
如果您有一个浮点数double num_float = 5.0;
和以下两个条件。
if(num_float > 3)
{
//...
}
if(num_float > 3.0)
{
//...
}
Q:由于3
转换为浮点,执行前一个比较会更慢吗?还是真的没有任何区别?
显然,我认为时间延迟最多可以忽略不计,但在while(1)循环中,我认为从长远来看,可能会损失相当大的时间(如果真的更慢的话)。
由于"as if"规则,编译器可以在编译时将文字转换为浮点值。如果能产生更好的代码,那么一个好的编译器就能做到这一点。
为了为编译器和目标平台明确回答您的问题,您需要检查编译器发出的内容以及它的执行方式。然而,如果任何主流编译器都没有将两个if语句中的任何一个转换为尽可能高效的代码,我会感到惊讶。
如果值是常量,那么应该没有任何区别,因为编译器将在编译过程中将常量转换为浮点值[除非编译器决定使用"将浮点值与整数进行比较"指令]。
如果该值是一个整数VARIABLE,那么将有一条额外的指令将整数值转换为浮点值[再次,除非编译器可以使用"将浮点值与整数进行比较"指令]。
增加到整个过程的时间(如果有的话)在很大程度上取决于什么处理器、浮点指令如何工作等。
对于性能真正重要的任何事情,衡量备选方案。最好是在一种以上类型的硬件上(例如,如果是PC,则同时使用AMD和Intel处理器),然后决定哪种是更好的选择。否则,您可能会发现自己调整了代码,使其在硬件上运行良好,但在其他硬件上运行更差。这不是一个好的优化-除非你唯一运行的机器是你自己的。
注意:这需要在目标硬件上重复。下面的代码很好地展示了所说的内容。
带常数:
bool with_int(const double num_float) {
return num_float > 3;
}
bool with_float(const double num_float) {
return num_float > 3.0;
}
g++4.7.2(-O3 -march=native
):
with_int(double):
ucomisd .LC0(%rip), %xmm0
seta %al
ret
with_float(double):
ucomisd .LC0(%rip), %xmm0
seta %al
ret
.LC0:
.long 0
.long 1074266112
clang 3.0(-O3 -march=native
):
.LCPI0_0:
.quad 4613937818241073152 # double 3.000000e+00
with_int(double): # @with_int(double)
ucomisd .LCPI0_0(%rip), %xmm0
seta %al
ret
.LCPI1_0:
.quad 4613937818241073152 # double 3.000000e+00
with_float(double): # @with_float(double)
ucomisd .LCPI1_0(%rip), %xmm0
seta %al
ret
结论:与常数相比没有差异。
带变量:
bool with_int(const double a, const int b) {
return a > b;
}
bool with_float(const double a, const float b) {
return a > b;
}
g++4.7.2(-O3 -march=native
):
with_int(double, int):
cvtsi2sd %edi, %xmm1
ucomisd %xmm1, %xmm0
seta %al
ret
with_float(double, float):
unpcklps %xmm1, %xmm1
cvtps2pd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
seta %al
ret
clang 3.0(-O3 -march=native
):
with_int(double, int): # @with_int(double, int)
cvtsi2sd %edi, %xmm1
ucomisd %xmm1, %xmm0
seta %al
ret
with_float(double, float): # @with_float(double, float)
cvtss2sd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
seta %al
ret
结论:正如Mats Peterson的回答所解释的那样,当与变量进行比较时,发出的指令会有所不同。
Q:由于3转换为浮点,执行前一个比较会更慢吗?还是真的没有任何区别?
A) 只需将其指定为一个整数。有些芯片有一条特殊的指令,用于在运行时与整数进行比较,但这并不重要,因为编译器会选择最好的。在某些情况下,它可能会在编译时根据目标体系结构将其转换为3.0。在其他情况下,它会将其保留为int。但因为您想要3,所以指定"3"
显然,我认为时间延迟最多可以忽略不计,但在while(1)循环中,我认为从长远来看,可能会损失相当大的时间(如果真的更慢的话)。
A) 编译器不会对这样的代码做任何奇怪的事情。它会选择最好的东西,所以不应该有时间延迟。对于数字常量,编译器可以自由地做最好的事情,不管它看起来是什么,只要它产生相同的结果。但是,您根本不希望在while循环中复合这种类型的比较。而是使用整数循环计数器。浮点循环计数器会慢很多。如果必须使用浮点作为循环计数器,则首选单点32位数据类型,并尽可能少地进行比较。
例如,您可以将问题分解为多个循环。
int x = 0;
float y = 0;
float finc = 0.1;
int total = 1000;
int num_times = total / finc;
num_times -= 2;// safety
// Run the loop in a safe zone using integer compares
while (x < num_times) {
// Do stuff
y += finc;
x++;
}
// Now complete the loop using float compares
while (y < total) {
y+= finc;
}
这将导致比较速度的大幅提高。
- 为什么在全局范围内使用"extern int a"似乎不行?
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- C++ - 最坏情况和平均情况插入时间复杂度在 std::unordered_map <int,int>?
- 没有从"int"到"时间"的可行转换
- 超过CPU时间限制:当MPI_Sent一个非常大的int*时
- 无法将 int 类型转换为时间类型(我的类类型)
- 通过引用传递基元类型(如 int、bool)是否比按值传递有任何加速?还是会恶化时间/空间的使用
- 如何在C++中将无符号的 int 64 转换为时间
- 解析时间戳char到INT进行计算
- 单元测试 - 仅在"int main()"左右重新编译以减少编译时间
- 崩溃时间(运算符 new(无符号 int)+22)
- 在与时间一起使用 srand 时,如果我没有time_t参数明确地将参数转换为无符号的 int 参数,这有关系吗?
- 从int到长时间进行打字
- 使用强制转换和设置填充将 int 值更改为时间
- 将系统时间 int 转换为格式化的时间字符串
- 获取系统时间(以毫秒为单位)作为int/double
- 如何用O(n)个时间和O(1)个空间对n个对象的群进行排序.每个对象有两个字段:int和string
- Unix时间作为本地时间的int
- ' const int a = 1; '是' a '一个常量表达式,如果' a '具有自动存储持续时间
- float与int比较所需的额外时间