【发布时间】:2013-12-09 21:29:39
【问题描述】:
我执行了一些基准测试来比较双精度和浮点性能。看到双打比浮点快得多,我感到非常惊讶。
我看到了一些关于这个的讨论,例如:
Is using double faster than float?
Are doubles faster than floats in c#?
他们中的大多数人表示,由于双精度优化等原因,可能 double 和 float 性能会相似。但是我看到使用双打时 x2 的性能提升!!这怎么可能?最糟糕的是,我使用的是 32 位机器,根据一些帖子,它确实有望在浮点数上表现更好......
我使用 C# 对其进行了精确检查,但我发现类似的 C++ 实现具有类似的行为。
我用来检查的代码:
static void Main(string[] args)
{
double[,] doubles = new double[64, 64];
float[,] floats = new float[64, 64];
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
s.Restart();
CalcDoubles(doubles);
s.Stop();
long doubleTime = s.ElapsedMilliseconds;
s.Restart();
CalcFloats(floats);
s.Stop();
long floatTime = s.ElapsedMilliseconds;
Console.WriteLine("Doubles time: " + doubleTime + " ms");
Console.WriteLine("Floats time: " + floatTime + " ms");
}
private static void CalcDoubles(double[,] arr)
{
unsafe
{
fixed (double* p = arr)
{
for (int b = 0; b < 192 * 12; ++b)
{
for (int i = 0; i < 64; ++i)
{
for (int j = 0; j < 64; ++j)
{
double* addr = (p + i * 64 + j);
double arrij = *addr;
arrij = arrij == 0 ? 1.0f / (i * j) : arrij * (double)i / j;
*addr = arrij;
}
}
}
}
}
}
private static void CalcFloats(float[,] arr)
{
unsafe
{
fixed (float* p = arr)
{
for (int b = 0; b < 192 * 12; ++b)
{
for (int i = 0; i < 64; ++i)
{
for (int j = 0; j < 64; ++j)
{
float* addr = (p + i * 64 + j);
float arrij = *addr;
arrij = arrij == 0 ? 1.0f / (i * j) : arrij * (float)i / j;
*addr = arrij;
}
}
}
}
}
}
我正在使用一个性能很差的笔记本:Intel Atom N455 处理器(双核,1.67GHz,32 位),2GB RAM。
【问题讨论】:
-
感谢您的回复。请注意,在双精度和浮点情况下,计数器都会以相同的偏移量递增(它是在 for 循环中手动计算的)。
-
你不需要不安全的代码来重现这个。如果将赋值移回数组,效果就会消失。
-
你是对的,它也发生在我的机器上。那为什么呢?也许缓存回写/直写策略(如前所述)?
-
@ZongZhengLi 这支持这样的假设,即使用双精度执行计算,并且浮点的额外处理时间专门用于将它们转换为 32 位格式以存储在数组中。跨度>
标签: c# performance intel processor