#include <math.h>
#include <stdio.h>
int main()
{
int volatile a=10,b=12;
int i, sum = 0;
for (i = 0; i < 1000000000; i++)
sum += a % b;
printf("%d\n", sum);
return 0;
}
运行时间:九点零七秒。
#include <math.h>
#include <stdio.h>
int main()
{
int volatile a=10,b=12;
int i, sum = 0;
for (i = 0; i < 1000000000; i++)
sum += (int)fmod(a, b);
printf("%d\n", sum);
return 0;
}
4条答案
按热度按时间x4shl7ld1#
选择
fmod
而不是%
可能有性能方面的原因,还是仅仅是一段奇怪的代码?fmod
在具有高延迟IDIV
指令的架构上可能会快一点,这需要(比如)大约50个周期或更多,因此fmod
的函数调用和int <---> double
转换成本可以分摊。根据Agner's Fog instruction tables,
IDIV
在AMD K10架构上需要24-55个时钟周期,与现代Intel Haswell相比,其延迟范围被列为22-29个时钟周期,但如果没有依赖链,相反的吞吐量在Intel上要好得多,为8-11个时钟周期。628mspwn2#
fmod
可能比所选体系结构上的整数除法快一点点。然而注意,如果
n
在编译时具有已知的非零值,则matrix[i] % n
将被编译为具有小调整的乘法,这应当比整数模数和浮点模数快得多。另一个有趣的区别是
n == 0
和INT_MIN % -1
上的行为。整数模运算调用未定义的溢出行为,这在许多当前架构上导致异常程序终止。相反,浮点模没有这些极端情况,结果是+Infinity
、-Infinity
、Nan
取决于matrix[i]
和-INT_MIN
的值,所有这些值都超过int
的范围,并且转换回int
是实现定义的,但通常不会导致异常程序终止。这可能是最初的程序员选择这个令人惊讶的解决方案的原因。xlpyo6sf3#
从实验上看(与直觉相反),
fmod
比%
快--至少在 * AMD Phenom(tm)II X4 955上是这样,它具有6400 bogomips *。下面是两个使用其中一种技术的程序,都使用相同的编译器(GCC)和相同的选项(cc -O3 foo.c -lm
)编译,并且运行在相同的硬件上:运行时间:九点零七秒。
运行时间:8.04秒
q5lcpyga4#
fmod()肯定总是比整数除法慢,因为减法和移位操作不在硬件中。下面的代码显示了我的fmod()实现:
你真的认为这个比我电脑上的glibc快100%到150%的代码可以和硬连线的div-instruction竞争吗?