我做了一些计时测试,还阅读了一些类似这篇文章(最后评论),看起来在 Release 构建中,float 和 double 值需要相同的处理时间。
这怎么可能?当浮点数与双精度值相比不太精确且更小时,CLR 如何在相同的处理时间内获得双精度值?
我做了一些计时测试,还阅读了一些类似这篇文章(最后评论),看起来在 Release 构建中,float 和 double 值需要相同的处理时间。
这怎么可能?当浮点数与双精度值相比不太精确且更小时,CLR 如何在相同的处理时间内获得双精度值?
至少在 x86 处理器上,float并且double每个都将由 FPU 转换为 10 字节实数进行处理。FPU 没有针对它支持的不同浮点类型的单独处理单元。
float比 100 年前应用更快的古老建议,double当时大多数 CPU 没有内置 FPU(而且很少有人拥有单独的 FPU 芯片),因此大多数浮点操作都是在软件中完成的。在这些机器上(由熔岩坑产生的蒸汽提供动力),使用s float. 现在,s 唯一真正的好处float是它们占用的空间更少(这只有在你拥有数百万个空间时才重要)。
它取决于32 位或64 位系统。如果编译为 64 位,double 会更快。在 64 位(机器和操作系统)上编译为 32 位,浮点运算速度提高了 30% 左右:
public static void doubleTest(int loop)
{
Console.Write("double: ");
for (int i = 0; i < loop; i++)
{
double a = 1000, b = 45, c = 12000, d = 2, e = 7, f = 1024;
a = Math.Sin(a);
b = Math.Asin(b);
c = Math.Sqrt(c);
d = d + d - d + d;
e = e * e + e * e;
f = f / f / f / f / f;
}
}
public static void floatTest(int loop)
{
Console.Write("float: ");
for (int i = 0; i < loop; i++)
{
float a = 1000, b = 45, c = 12000, d = 2, e = 7, f = 1024;
a = (float) Math.Sin(a);
b = (float) Math.Asin(b);
c = (float) Math.Sqrt(c);
d = d + d - d + d;
e = e * e + e * e;
f = f / f / f / f / f;
}
}
static void Main(string[] args)
{
DateTime time = DateTime.Now;
doubleTest(5 * 1000000);
Console.WriteLine("milliseconds: " + (DateTime.Now - time).TotalMilliseconds);
time = DateTime.Now;
floatTest(5 * 1000000);
Console.WriteLine("milliseconds: " + (DateTime.Now - time).TotalMilliseconds);
Thread.Sleep(5000);
}
我有一个使用 CUDA 的小项目,我记得 float 也比 double 快。一旦主机和设备之间的流量较低(主机是 CPU 和“正常”RAM,设备是 GPU 和相应的 RAM)。但即使数据一直驻留在设备上,它也会变慢。我想我在某处读到过这种情况最近发生了变化,或者应该随着下一代发生变化,但我不确定。
因此,在这些情况下,GPU 似乎根本无法原生处理双精度,这也可以解释为什么通常使用 GLFloat 而不是 GLDouble。
(正如我所说,这只是我所记得的,只是在 CPU 上搜索 float 与 double 时偶然发现了这一点。)
然而,在某些情况下,浮点数仍然是首选——例如,对于 OpenGL 编码,使用 GLFloat 数据类型(通常直接映射到 16 位浮点数)更为常见,因为它在大多数 GPU 上比 GLDouble 更有效。