【发布时间】:2011-03-18 14:20:04
【问题描述】:
我最近阅读了这篇文章:Floating point vs integer calculations on modern hardware,并对我自己的处理器在这个准基准上的性能感到好奇,所以我将两个版本的代码放在一起,一个是 C#,一个是 C++(Visual Studio 2010 Express)并通过优化对它们进行编译以查看结果。我的 C# 版本的输出相当合理:
int add/sub: 350ms
int div/mul: 3469ms
float add/sub: 1007ms
float div/mul: 67493ms
double add/sub: 1914ms
double div/mul: 2766ms
当我编译并运行 C++ 版本时,我发现了一些完全不同的东西:
int add/sub: 210.653ms
int div/mul: 2946.58ms
float add/sub: 3022.58ms
float div/mul: 172931ms
double add/sub: 1007.63ms
double div/mul: 74171.9ms
我预计会有一些性能差异,但不会这么大!我不明白为什么 C++ 中的除法/乘法比加法/减法慢得多,其中托管的 C# 版本对我的期望更合理。该函数的C++版本代码如下:
template< typename T> void GenericTest(const char *typestring)
{
T v = 0;
T v0 = (T)((rand() % 256) / 16) + 1;
T v1 = (T)((rand() % 256) / 16) + 1;
T v2 = (T)((rand() % 256) / 16) + 1;
T v3 = (T)((rand() % 256) / 16) + 1;
T v4 = (T)((rand() % 256) / 16) + 1;
T v5 = (T)((rand() % 256) / 16) + 1;
T v6 = (T)((rand() % 256) / 16) + 1;
T v7 = (T)((rand() % 256) / 16) + 1;
T v8 = (T)((rand() % 256) / 16) + 1;
T v9 = (T)((rand() % 256) / 16) + 1;
HTimer tmr = HTimer();
tmr.Start();
for (int i = 0 ; i < 100000000 ; ++i)
{
v += v0;
v -= v1;
v += v2;
v -= v3;
v += v4;
v -= v5;
v += v6;
v -= v7;
v += v8;
v -= v9;
}
tmr.Stop();
// I removed the bracketed values from the table above, they just make the compiler
// assume I am using the value for something do it doesn't optimize it out.
cout << typestring << " add/sub: " << tmr.Elapsed() * 1000 << "ms [" << (int)v << "]" << endl;
tmr.Start();
for (int i = 0 ; i < 100000000 ; ++i)
{
v /= v0;
v *= v1;
v /= v2;
v *= v3;
v /= v4;
v *= v5;
v /= v6;
v *= v7;
v /= v8;
v *= v9;
}
tmr.Stop();
cout << typestring << " div/mul: " << tmr.Elapsed() * 1000 << "ms [" << (int)v << "]" << endl;
}
C# 测试的代码不是通用的,而是这样实现的:
static double DoubleTest()
{
Random rnd = new Random();
Stopwatch sw = new Stopwatch();
double v = 0;
double v0 = (double)rnd.Next(1, int.MaxValue);
double v1 = (double)rnd.Next(1, int.MaxValue);
double v2 = (double)rnd.Next(1, int.MaxValue);
double v3 = (double)rnd.Next(1, int.MaxValue);
double v4 = (double)rnd.Next(1, int.MaxValue);
double v5 = (double)rnd.Next(1, int.MaxValue);
double v6 = (double)rnd.Next(1, int.MaxValue);
double v7 = (double)rnd.Next(1, int.MaxValue);
double v8 = (double)rnd.Next(1, int.MaxValue);
double v9 = (double)rnd.Next(1, int.MaxValue);
sw.Start();
for (int i = 0; i < 100000000; i++)
{
v += v0;
v -= v1;
v += v2;
v -= v3;
v += v4;
v -= v5;
v += v6;
v -= v7;
v += v8;
v -= v9;
}
sw.Stop();
Console.WriteLine("double add/sub: {0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
v /= v0;
v *= v1;
v /= v2;
v *= v3;
v /= v4;
v *= v5;
v /= v6;
v *= v7;
v /= v8;
v *= v9;
}
sw.Stop();
Console.WriteLine("double div/mul: {0}", sw.ElapsedMilliseconds);
sw.Reset();
return v;
}
这里有什么想法吗?
【问题讨论】:
-
您在 C++ 中使用了哪些优化设置?您是否在 Visual Studio 的测试主机中运行此程序(时间对我来说似乎很慢......)?
-
它们对我来说似乎也很慢。我从命令行运行它,完整程序优化,优化速度。 32 位 Windows XP。
-
当我尝试运行您的基准测试时,我得到了非常奇怪的结果,它似乎完全随机。有一次,
double和float的除法约为 200 毫秒,下一次可能高达 7000 毫秒。我运行它的迭代次数减少了 10 倍,否则当它出现时会花费很长时间。那是在 C# 方面,在 C++ 方面,我看到floatadd/sub 比 C# 慢 3 倍,并且除法在 7+ 秒时一直很慢。 -
@JulianR:这就是我在这里发布这个问题的原因,我不太明白为什么会有奇怪的性能差异。
标签: c# c++ performance floating-point