在SO中搜索.NET中浮点和双精度之间的性能差异之后,我整理了一个简单的基准测试了2种方法,每种方法都具有浮点和双精度,调试和释放。几次运行基准测试之后,我对x64发行版中Func2Double和Func2Float方法中float和double的计时结果感到困惑。 Func2Double的行为(缓慢的基准测试时间)就像是调试版本一样。其他方法(Func1Double,Func1Float,Func2Float)都产生了比调试方法更快的基准时间(按预期)。我对x64发行版的float版本和double版本的IL进行了比较,但是没有发现任何明显的差异可以解释我得到的结果。
有人能在BenchmarkFloatVsDouble-x64-release.exe中解释Func2Double的基准测试结果如何吗?
这是我测试过的源代码:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace BenchmarkFloatVsDouble
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("OSDescription: {0}", RuntimeInformation.OSDescription);
Console.WriteLine("OSArchitecture: {0}", RuntimeInformation.OSArchitecture);
Console.WriteLine("ProcessArchitecture: {0}", RuntimeInformation.ProcessArchitecture);
Console.WriteLine("FrameworkDescription: {0}", RuntimeInformation.FrameworkDescription);
Console.WriteLine();
var ev = Environment.GetEnvironmentVariables();
Console.WriteLine("PROCESSOR_ARCHITEW6432: {0}", ev["PROCESSOR_ARCHITEW6432"]);
Console.WriteLine("PROCESSOR_ARCHITECTURE: {0}", ev["PROCESSOR_ARCHITECTURE"]);
Console.WriteLine("PROCESSOR_IDENTIFIER: {0}", ev["PROCESSOR_IDENTIFIER"]);
Console.WriteLine("NUMBER_OF_PROCESSORS: {0}", ev["NUMBER_OF_PROCESSORS"]);
Console.WriteLine();
Console.WriteLine("Is64BitProcess: {0}", Environment.Is64BitProcess);
Console.WriteLine("Is64BitOperatingSystem: {0}", Environment.Is64BitOperatingSystem);
Console.WriteLine();
using (var p = Process.GetCurrentProcess())
{
p.PriorityClass = ProcessPriorityClass.RealTime;
}
var template = "{0,15}, {1,15}, {2,15}, {3,15}";
Console.WriteLine(
template,
"Func1Double",
"Func1Float",
"Func2Double",
"Func2Float");
var count = 100 * 1000 * 1000;
var v1 = 1.23456789D;
var v2 = 1.23456789F;
for (var ii = 0; ii < 10; ii++)
{
var t1 = Environment.TickCount;
for (var i = 0; i < count; i++) Func1Double(v1);
var d1 = Environment.TickCount - t1;
var t2 = Environment.TickCount;
for (var i = 0; i < count; i++) Func1Float(v2);
var d2 = Environment.TickCount - t2;
var t3 = Environment.TickCount;
for (var i = 0; i < count; i++) Func2Double(v1);
var d3 = Environment.TickCount - t3;
var t4 = Environment.TickCount;
for (var i = 0; i < count; i++) Func2Float(v2);
var d4 = Environment.TickCount - t4;
Console.WriteLine(template, d1, d2, d3, d4);
}
Console.WriteLine("Done");
Console.ReadKey();
}
public static double Func1Double(double x)
{
return Math.Exp(-x * x);
}
public static float Func1Float(float x)
{
return (float)Math.Exp(-x * x);
}
public static double Func2Double(double x)
{
return 1d - (1d / (1d + (x * x)));
}
public static float Func2Float(float x)
{
return 1f - (1f / (1f + (x * x)));
}
}
}
这是我创建可执行文件的方式。我知道我可以在VS中完成4个版本(x86 / x64 x调试/发行版)的批处理构建,但是我希望能够在此处显示所有步骤。我对.NET 4附带的csc.exe进行了相同的测试,但是得到了相同的结果。
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>csc /platform:x64 /optimize- /debug+ /debug:full /define:DEBUG;TRACE /out:BenchmarkFloatVsDouble-x64-debug.exe Program.cs
Microsoft (R) Visual C# Compiler version 3.2.0-beta4-19380-04 (5e176ad8)
Copyright (C) Microsoft Corporation. All rights reserved.
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>csc /platform:x64 /optimize+ /debug- /debug:pdbonly /define:TRACE /out:BenchmarkFloatVsDouble-x64-release.exe Program.cs
Microsoft (R) Visual C# Compiler version 3.2.0-beta4-19380-04 (5e176ad8)
Copyright (C) Microsoft Corporation. All rights reserved.
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>csc /platform:x86 /optimize- /debug+ /debug:full /define:DEBUG;TRACE /out:BenchmarkFloatVsDouble-x86-debug.exe Program.cs
Microsoft (R) Visual C# Compiler version 3.2.0-beta4-19380-04 (5e176ad8)
Copyright (C) Microsoft Corporation. All rights reserved.
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>csc /platform:x86 /optimize+ /debug- /debug:pdbonly /define:TRACE /out:BenchmarkFloatVsDouble-x86-release.exe Program.cs
Microsoft (R) Visual C# Compiler version 3.2.0-beta4-19380-04 (5e176ad8)
Copyright (C) Microsoft Corporation. All rights reserved.
这是运行4个不同版本的结果。
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>BenchmarkFloatVsDouble-x64-release.exe
OSDescription: Microsoft Windows 10.0.16299
OSArchitecture: X64
ProcessArchitecture: X64
FrameworkDescription: .NET Framework 4.7.3416.0
PROCESSOR_ARCHITEW6432:
PROCESSOR_ARCHITECTURE: AMD64
PROCESSOR_IDENTIFIER: Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
NUMBER_OF_PROCESSORS: 8
Is64BitProcess: True
Is64BitOperatingSystem: True
Func1Double, Func1Float, Func2Double, Func2Float
31, 31, 375, 32
31, 15, 375, 32
31, 31, 391, 31
31, 16, 375, 31
31, 16, 375, 31
32, 31, 375, 15
32, 31, 375, 16
31, 31, 375, 16
31, 31, 375, 16
16, 31, 375, 32
Done
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>BenchmarkFloatVsDouble-x86-release.exe
OSDescription: Microsoft Windows 10.0.16299
OSArchitecture: X64
ProcessArchitecture: X86
FrameworkDescription: .NET Framework 4.7.3416.0
PROCESSOR_ARCHITEW6432: AMD64
PROCESSOR_ARCHITECTURE: x86
PROCESSOR_IDENTIFIER: Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
NUMBER_OF_PROCESSORS: 8
Is64BitProcess: False
Is64BitOperatingSystem: True
Func1Double, Func1Float, Func2Double, Func2Float
1219, 1203, 375, 375
1219, 1203, 375, 375
1219, 1203, 375, 375
1219, 1234, 375, 375
1219, 1219, 375, 375
1234, 1219, 375, 375
1218, 1219, 375, 375
1219, 1203, 375, 375
1219, 1219, 375, 375
1218, 1250, 375, 375
Done
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>BenchmarkFloatVsDouble-x64-debug.exe
OSDescription: Microsoft Windows 10.0.16299
OSArchitecture: X64
ProcessArchitecture: X64
FrameworkDescription: .NET Framework 4.7.3416.0
PROCESSOR_ARCHITEW6432:
PROCESSOR_ARCHITECTURE: AMD64
PROCESSOR_IDENTIFIER: Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
NUMBER_OF_PROCESSORS: 8
Is64BitProcess: True
Is64BitOperatingSystem: True
Func1Double, Func1Float, Func2Double, Func2Float
1453, 1547, 485, 453
1437, 1531, 454, 453
1407, 1500, 453, 453
1422, 1515, 453, 469
1406, 1500, 469, 453
1391, 1500, 453, 469
1406, 1500, 453, 469
1422, 1500, 453, 469
1390, 1500, 469, 453
1406, 1516, 469, 469
Done
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>BenchmarkFloatVsDouble-x86-debug.exe
OSDescription: Microsoft Windows 10.0.16299
OSArchitecture: X64
ProcessArchitecture: X86
FrameworkDescription: .NET Framework 4.7.3416.0
PROCESSOR_ARCHITEW6432: AMD64
PROCESSOR_ARCHITECTURE: x86
PROCESSOR_IDENTIFIER: Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
NUMBER_OF_PROCESSORS: 8
Is64BitProcess: False
Is64BitOperatingSystem: True
Func1Double, Func1Float, Func2Double, Func2Float
1719, 1672, 484, 469
1719, 1687, 484, 454
1718, 1688, 484, 469
1703, 1688, 484, 453
1734, 1750, 500, 485
1750, 1750, 500, 469
1765, 1735, 500, 468
1766, 1687, 485, 469
1703, 1687, 485, 468
1766, 1719, 484, 500
Done
以及用于生成IL以便更仔细检查的命令。
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>ildasm BenchmarkFloatVsDouble-x64-debug.exe /out=BenchmarkFloatVsDouble-x64-debug.exe.il
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>ildasm BenchmarkFloatVsDouble-x64-release.exe /out=BenchmarkFloatVsDouble-x64-release.exe.il
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>ildasm BenchmarkFloatVsDouble-x86-debug.exe /out=BenchmarkFloatVsDouble-x86-debug.exe.il
D:\files\dev\BenchmarkFloatVsDouble\BenchmarkFloatVsDouble>ildasm BenchmarkFloatVsDouble-x86-release.exe /out=BenchmarkFloatVsDouble-x86-release.exe.il