我很好奇大型结构的开销与使用运算符+和*数学的小结构.所以我做了两个结构,一个Small有1个双字段(8个字节),另一个Big有10个双字节(80个字节).在我的所有操作中,我只操纵一个叫做的字段x.
首先,我在两个结构中都定义了数学运算符
public static Small operator +(Small a, Small b)
{
return new Small(a.x + b.x);
}
public static Small operator *(double x, Small a)
{
return new Small(x * a.x);
}
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,它会占用堆栈中的大量内存来复制字段.我运行了5,000,000次迭代的数学运算并得到了我怀疑的(3倍减速).
public double TestSmall()
{
pt.Start(); // pt = performance timing object
Small r = new Small(rnd.NextDouble()); //rnd = Random number generator
for (int i = 0; i < N; i++)
{
a = 0.6 * a + 0.4 * r; // a is a local field of type Small
}
pt.Stop();
return pt.ElapsedSeconds;
}
Run Code Online (Sandbox Code Playgroud)
发布代码的结果(以秒为单位)
Small=0.33940 Big=0.98909 Big is Slower by x2.91
Run Code Online (Sandbox Code Playgroud)
现在为有趣的部分.我使用带ref参数的静态方法定义相同的操作
public static void Add(ref Small a, ref Small b, ref Small res)
{
res.x = a.x + b.x;
}
public static void Scale(double x, ref Small a, ref Small res)
{
res.x = x * a.x;
}
Run Code Online (Sandbox Code Playgroud)
并在此测试代码上运行相同数量的迭代:
public double TestSmall2()
{
pt.Start(); // pt = performance timing object
Small a1 = new Small(); // local
Small a2 = new Small(); // local
Small r = new Small(rnd.NextDouble()); //rdn = Random number generator
for (int i = 0; i < N; i++)
{
Small.Scale(0.6, ref a, ref a1);
Small.Scale(0.4, ref r, ref a2);
Small.Add(ref a1, ref a2, ref a);
}
pt.Stop();
return pt.ElapsedSeconds;
}
Run Code Online (Sandbox Code Playgroud)
结果显示(以秒为单位)
Small=0.11765 Big=0.07130 Big is Slower by x0.61
Run Code Online (Sandbox Code Playgroud)
因此,与mem-copy密集型运算符相比,我获得了x3和x14的加速,这很好,但是将Small结构时间与Big进行比较,你会发现Small 比Big 慢 60%.
有谁能解释一下?是否与CPU流水线有关并且在(空间)内存中分离操作可以更有效地预取数据?
如果你想自己试试这个,请从我的保管箱中获取代码http://dl.dropbox.com/u/11487099/SmallBigCompare.zip
我无法重现你的结果。Big在我的盒子上,“ref”版本的和 的性能基本相同Small,在容差范围内。
(在不附加调试器的情况下运行发布模式,迭代次数为 10 或 100 倍,只是为了获得良好的长期运行。)
您是否尝试过多次迭代运行您的版本?是否有可能在测试运行时,您的 CPU 逐渐提高其时钟速度(因为它发现它必须努力工作)?
| 归档时间: |
|
| 查看次数: |
207 次 |
| 最近记录: |