我做了一些计时测试,还阅读了一些类似这篇文章(最后评论),看起来在 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 更有效。