我做了一些计时测试,还读了一些类似这样的文章(最后评论),在Release build中,float和double值看起来花费了相同的处理时间。
这怎么可能?当float比double值精度低且较小时,CLR如何在相同的处理时间内将double值加倍?
我做了一些计时测试,还读了一些类似这样的文章(最后评论),在Release build中,float和double值看起来花费了相同的处理时间。
这怎么可能?当float比double值精度低且较小时,CLR如何在相同的处理时间内将double值加倍?
Answers:
在x86处理器,至少,float
并且double
将每一个都可以由FPU进行处理转换成一个10字节的真实。FPU没有针对其支持的不同浮点类型的单独处理单元。
这种古老的建议float
比double
100年前的建议要快,当时大多数CPU没有内置FPU(很少有人拥有单独的FPU芯片),因此大多数浮点运算都是在软件中完成的。在这些机器上(这是由通过熔岩凹坑产生的蒸汽驱动的),它是更快地使用float
秒。现在,float
s 的唯一真正好处是它们占用的空间更少(仅当您拥有数百万个它们时才重要)。
我有一个使用CUDA的小项目,并且我还记得浮点数比那里的两倍还快。一旦主机和设备之间的流量降低(主机是CPU,“正常” RAM,设备是GPU和那里的相应RAM)。但是,即使数据始终驻留在设备上,速度也会变慢。我想我读过某个地方,这种情况最近已经改变,或者应该随着下一代的改变而改变,但是我不确定。
因此,在这种情况下,GPU似乎根本无法固有地处理双精度,这也可以解释为什么通常使用GLFloat而不是GLDouble。
(正如我所说的那样,仅在我想起时,在搜索CPU上的float与double时偶然发现了这一点。)
但是,在某些情况下,首选使用浮点数-例如,使用OpenGL编码,更常见的是使用GLFloat数据类型(通常直接映射到16位浮点数),因为在大多数GPU上,它比GLDouble效率更高。
它取决于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);
}
Math
使用double,因此强制转换是问题的一部分。但是您误读了我的文章:我的测试表明我的表现更好。
float
和double
性能实际上是相同的。在许多独立试验中求平均值时,相差不到0.3%,在该试验中,每个试验对连续链接的变量进行乘,除和加法运算(以避免妨碍编译器优化)。我使用Math.Sin()
和进行了第二组测试,Math.Sqrt()
结果也相同。