为什么 C# double 算法似乎比 long 算法更快?
Why C# arithmetic on double appears to be faster than arithmetic on long?
以下代码令人惊讶的输出显示 double 运算比 long 运算快几乎 100%:
Test_DivOperator Float arithmetic measured time: 15974.5024 ms.
Test_DivOperator Integer arithmetic measured time: 28548.183 ms.
使用的构建设置是.Net4.5 C# 5.0(平台目标:x64)
使用的硬件是Intel Core i5-2520M (运行 Windows7 64Bit)
注意:使用的运算符(这里是除法)确实会影响结果,除法最大化这个观察
const int numOfIterations = 1; //this value takes memory access out of the game
const int numOfRepetitions = 500000000; //CPU bound application
Random rand = new Random();
double[] Operand1 = new double[numOfIterations];
double[] Operand2 = new double[numOfIterations];
double[] Operand3 = new double[numOfIterations];
long[] Int64Operand1 = new long[numOfIterations];
long[] Int64Operand2 = new long[numOfIterations];
long[] Int64Operand3 = new long[numOfIterations];
for (int i = 0; i < numOfIterations; i++)
{
Operand1[i]=(rand.NextDouble() * 100);
Operand2[i]=(rand.NextDouble() * 80);
Operand3[i]=(rand.NextDouble() * 17);
Int64Operand1[i] = (long)Operand1[i];
Int64Operand2[i] = (long)Operand2[i]+1;
Int64Operand3[i] = (long)Operand3[i]+1;
}
double[] StdResult = new double[numOfIterations];
long[] NewResult = new long[numOfIterations];
TimeSpan begin = Process.GetCurrentProcess().TotalProcessorTime;
for (int j = 0; j < numOfRepetitions; j++)
{
for (int i = 0; i < numOfIterations; i++)
{
double result = Operand1[i] / Operand2[i];
result = result / Operand3[i];
StdResult[i]=(result);
}
}
TimeSpan end = Process.GetCurrentProcess().TotalProcessorTime;
Console.WriteLine("Test_DivOperator Float arithmetic measured time: " + (end - begin).TotalMilliseconds + " ms.");
begin = Process.GetCurrentProcess().TotalProcessorTime;
for (int j = 0; j < numOfRepetitions; j++)
{
for (int i = 0; i < numOfIterations; i++)
{
long result = Int64Operand1[i] / Int64Operand2[i];
result = result / Int64Operand3[i];
NewResult[i]=(result);
}
}
end = Process.GetCurrentProcess().TotalProcessorTime;
Console.WriteLine("Test_DivOperator Integer arithmetic measured time: " + (end - begin).TotalMilliseconds + " ms.");
这并不意外。 64 位整数除法就是这么慢。
您的处理器是 Sandy Bridge,观察 table 的延迟和吞吐量,64 位 idiv
的延迟比 divsd
高得多,吞吐量差得多。
其他微体系结构显示出类似的差异。
做实际的数学计算,每次迭代 2.8548183E10ns / 500000000 = 57ns,频率为 3.2GHz,大约 183 个周期,有两个除法和一些额外的开销,所以这并不奇怪。
对于双打,它达到了 32ns,102 个周期,实际上比我预期的要多。
以下代码令人惊讶的输出显示 double 运算比 long 运算快几乎 100%:
Test_DivOperator Float arithmetic measured time: 15974.5024 ms.
Test_DivOperator Integer arithmetic measured time: 28548.183 ms.
使用的构建设置是.Net4.5 C# 5.0(平台目标:x64)
使用的硬件是Intel Core i5-2520M (运行 Windows7 64Bit)
注意:使用的运算符(这里是除法)确实会影响结果,除法最大化这个观察
const int numOfIterations = 1; //this value takes memory access out of the game
const int numOfRepetitions = 500000000; //CPU bound application
Random rand = new Random();
double[] Operand1 = new double[numOfIterations];
double[] Operand2 = new double[numOfIterations];
double[] Operand3 = new double[numOfIterations];
long[] Int64Operand1 = new long[numOfIterations];
long[] Int64Operand2 = new long[numOfIterations];
long[] Int64Operand3 = new long[numOfIterations];
for (int i = 0; i < numOfIterations; i++)
{
Operand1[i]=(rand.NextDouble() * 100);
Operand2[i]=(rand.NextDouble() * 80);
Operand3[i]=(rand.NextDouble() * 17);
Int64Operand1[i] = (long)Operand1[i];
Int64Operand2[i] = (long)Operand2[i]+1;
Int64Operand3[i] = (long)Operand3[i]+1;
}
double[] StdResult = new double[numOfIterations];
long[] NewResult = new long[numOfIterations];
TimeSpan begin = Process.GetCurrentProcess().TotalProcessorTime;
for (int j = 0; j < numOfRepetitions; j++)
{
for (int i = 0; i < numOfIterations; i++)
{
double result = Operand1[i] / Operand2[i];
result = result / Operand3[i];
StdResult[i]=(result);
}
}
TimeSpan end = Process.GetCurrentProcess().TotalProcessorTime;
Console.WriteLine("Test_DivOperator Float arithmetic measured time: " + (end - begin).TotalMilliseconds + " ms.");
begin = Process.GetCurrentProcess().TotalProcessorTime;
for (int j = 0; j < numOfRepetitions; j++)
{
for (int i = 0; i < numOfIterations; i++)
{
long result = Int64Operand1[i] / Int64Operand2[i];
result = result / Int64Operand3[i];
NewResult[i]=(result);
}
}
end = Process.GetCurrentProcess().TotalProcessorTime;
Console.WriteLine("Test_DivOperator Integer arithmetic measured time: " + (end - begin).TotalMilliseconds + " ms.");
这并不意外。 64 位整数除法就是这么慢。
您的处理器是 Sandy Bridge,观察 table 的延迟和吞吐量,64 位 idiv
的延迟比 divsd
高得多,吞吐量差得多。
其他微体系结构显示出类似的差异。
做实际的数学计算,每次迭代 2.8548183E10ns / 500000000 = 57ns,频率为 3.2GHz,大约 183 个周期,有两个除法和一些额外的开销,所以这并不奇怪。
对于双打,它达到了 32ns,102 个周期,实际上比我预期的要多。