c# - 与结构大小和性能相关的特殊结果

标签 c# struct timing

我很好奇在使用运算符 +* 进行数学运算时,大型结构与小型结构的开销。所以我做了两个结构,一个 Small 有 1 个双字段(8 字节)和一个 Big 有 10 个 double 字段(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);
}

正如预期的那样,它会在堆栈中占用大量内存来复制字段。我运行了 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;
}

Release 代码的结果(以秒为单位)

Small=0.33940 Big=0.98909     Big is Slower by x2.91

现在是有趣的部分。我用带有 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;
}

并在此测试代码上运行相同次数的迭代:

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;
}

结果显示(以秒为单位)

Small=0.11765 Big=0.07130     Big is Slower by x0.61

因此,与内存复制密集型运算符相比,我得到了 x3 和 x14 的加速,这很好,但是将 Small 结构时间与 Big 进行比较,您会发现 Small 比 Big 慢 60% 比大。

谁能解释一下?它是否与 CPU 流水线有关,并且在(空间)内存中分离操作可以更有效地预取数据?

如果您想自己尝试,请从我的保管箱中获取代码 http://dl.dropbox.com/u/11487099/SmallBigCompare.zip

最佳答案

您的基准测试似乎存在一些缺陷。

  1. 使用Stopwatch 而不是PerformanceTimer 类型。我不熟悉后者,它似乎是第 3 方组件。尤其麻烦的是,它以 EllapsedSeconds 而不是 EllapsedMilliseconds 为单位测量时间。
  2. 应将每个测试运行两次并只计算第二次以消除潜在的 JIT 成本
  3. Marshal.SizeOf 不会产生结构的实际大小,只是它的编码大小。

切换到 Stopwatch 后,我看到基准测试按预期执行,在静态引用情况下两种类型的时间几乎相等。

关于c# - 与结构大小和性能相关的特殊结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3806839/

相关文章:

c++ - llvm 在 C++ 中提取结构元素和结构大小

python - 为什么 `{*l}` 比 `set(l)` 快 - python 集合(不仅仅是对于集合,对于所有序列)

java - Hadoop 作业执行所花费的时间

objective-c - OSX 上的单调时钟

c# - 是否可以在网络浏览器上打开和编辑 Excel 文件?

tomcat - 如何将 hdiv 与多个模块集成(在同一个 tomcat 中运行)

c# - Web API 将自定义异常抛回给客户端

添加到列表末尾的同一个链表函数可以用于添加到多个不同的链表吗?

c# - 部署 webAPI 服务器端所需的最少文件

c# - Excel 电子表格中缺少列