与结构尺寸和性能有关的特殊结果

ja7*_*a72 6 c# struct timing

我很好奇大型结构的开销与使用运算符+*数学的小结构.所以我做了两个结构,一个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

Jon*_*eet 1

我无法重现你的结果。Big在我的盒子上,“ref”版本的和 的性能基本相同Small,在容差范围内。

(在不附加调试器的情况下运行发布模式,迭代次数为 10 或 100 倍,只是为了获得良好的长期运行。)

您是否尝试过多次迭代运行您的版本?是否有可能在测试运行时,您的 CPU 逐渐提高其时钟速度(因为它发现它必须努力工作)?