关于在c语言中进行数学运算时的性能问题
代码X: 代码Y:关于在c语言中进行数学运算时的性能问题,c,performance,math,optimization,C,Performance,Math,Optimization,代码X: 代码Y: float result; int a, b; result = (float)a + (float)b; 哪种代码最快且使用的资源较少?此C代码: float result, a, b; result = a + b; 可能会使用优化编译器编译成如下内容: float test(int a, int b) { float result = (float)a + (float)b; return result; } float test1(float a,
float result;
int a, b;
result = (float)a + (float)b;
哪种代码最快且使用的资源较少?此C代码:
float result, a, b;
result = a + b;
可能会使用优化编译器编译成如下内容:
float test(int a, int b)
{
float result = (float)a + (float)b;
return result;
}
float test1(float a, float b)
{
float result = a + b;
return result;
}
因此您可以看到
test1
比test
做得少,这是正常的,因为两个函数做的事情不一样。在test1
中,一切都是float
,因此不需要进行转换。在test
中,在加法之前需要将int
s转换为float。您使用的是未初始化的变量,由于精度损失,这两段代码并不完全相同,但我将忽略这一点,让我们从概念上进行讨论
我假设在这两种情况下,“a”和“b”都是整数值,而不管它们的类型如何
首先,当谈到浮点运算时,它总是依赖于体系结构。没有任何处理器以相同的方式支持浮点操作
不过,好吧,假设您正在谈论x86_64
其次是优化。请注意(float)a+(float)b
与(float)(a+b)
不同,因为浮点转换可能会丢失精度(尽管对于int可能不会,但很长时间内肯定会丢失精度)。因此,该无法优化,或者至少在某些情况下无法优化
所以优化器可能不会在这两种情况之间产生太大的差异
现在,还要注意,从int到float和back的转换是一条单独的汇编指令(例如,与从int到long不同),因为整数和浮点数的mem格式不同,这就是cvtsi2ss
指令
结论:
第一种情况的计算量相同,但也有转换。所以它稍微慢一点
请参见此处说明差异的拆解:
案例1:
情况2:假设没有溢出,Y会稍微快一点,因为将
int
转换为float
会有开销
然而,差异将非常小,除非性能至关重要,否则良好做法是用最“自然”的数据类型而不是最性能的数据类型来表示a
和b
。也就是说,除非它们有一个分数部分(本质上)float
是不合适的,即使某些计算有float
结果
还请注意,float
可以表示精确整数的范围可能比int
窄。在典型的平台上,int
为32位,float
也为32位,但使用一些位对指数进行编码
在某些平台上,double
可能更快,因为float
在内部转换为double
并返回。
除非空间非常重要(例如,托管环境或微型嵌入式设备上有数百万个值),否则通常建议使用
double
。这两个示例完全不同,比较它们没有什么意义。为什么?
第一个exmaple将两个转换为浮点的整数相加。编译器必须将两者转换为float,然后添加它们
第二个示例只添加了两个浮点,没有任何转换
我相信你想比较一下
test:
cvtsi2ss xmm1, edi
cvtsi2ss xmm0, esi
addss xmm0, xmm1
ret
test1:
addss xmm0, xmm1
ret
函数栏的效率更高,但如果两个整数相加溢出(先相加,然后将结果转换为浮点),调用UB,则可能不会产生相同的结果。差异很小,因此可以忽略它。这两个代码的作用不同。两者都有未定义的行为,尽管变量未初始化。没有上下文,这个问题毫无意义。在这两种情况下,
a
或b
之前必须给定一些值。因此,在一种情况下,先前的代码使用int
为a
和b
生成int
值,在另一种情况下,使用float
为a
和b
生成float
值。因此,使用代码X或代码Y的两个程序之间的差异不仅仅在于代码X或代码Y,因此,它们执行的时间差不仅仅是由于代码X或代码Y。更快的回答也必须取决于程序的其他部分。@EugeneSh:在其他代码之前显示声明是显示变量类型的常见约定,并不意味着程序中的代码实际上只包含这些声明紧接着是显示的其他代码。您现在应该知道了。注意(float)a+(float)b与(float)(a+b)不同,因为浮点转换可能会失去精度
问题在其他地方。
float foo(int a, int b) {
return (float)a + (float)b;
}
float bar(int a, int b) {
return a + b;
}
The resulting code
pxor xmm0, xmm0
pxor xmm1, xmm1
cvtsi2ss xmm0, edi
cvtsi2ss xmm1, esi
addss xmm0, xmm1
ret
bar:
add edi, esi
pxor xmm0, xmm0
cvtsi2ss xmm0, edi
ret