c - 基准测试时如何使缓存无效?

标签 c caching benchmarking cache-invalidation

我有这段代码,当交换 UsingAs 和 UsingCast 的顺序时,它们的性能也会交换。

using System;
using System.Diagnostics;
using System.Linq;

using System.IO;

class Test
{
    const int Size = 30000000;

    static void Main()
    {
        object[] values = new MemoryStream[Size];



        UsingAs(values);
        UsingCast(values);


        Console.ReadLine();
    }

    static void UsingCast(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            if (o is MemoryStream)
            {
                var m = (MemoryStream)o;
                sum += (int)m.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("Cast: {0} : {1}", sum,
                          (long)sw.ElapsedMilliseconds);
    }

    static void UsingAs(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {

            if (o is MemoryStream)
            {
                var m = o as MemoryStream;
                sum += (int)m.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("As: {0} : {1}", sum,
                          (long)sw.ElapsedMilliseconds);
    }


}

输出:

As: 0 : 322
Cast: 0 : 281

当这样做...

UsingCast(values);
UsingAs(values);

...结果:

Cast: 0 : 322
As: 0 : 281

当这样做时...

UsingAs(values);

...结果:

As: 0 : 322

当这样做时:

UsingCast(values);

...结果:

Cast: 0 : 322

除了独立运行它们之外,如何使缓存无效以使第二个被基准测试的代码不会收到第一个代码的缓存内存?

撇开基准测试不谈,只是喜欢现代处理器执行这种缓存魔法的事实:-)

[编辑]

按照建议尝试这个更快的代码(据说)...

static void UsingAsAndNullTest(object[] values)
{        
    Stopwatch sw = Stopwatch.StartNew();
    int sum = 0;
    foreach (object o in values)
    {
        var m = o as MemoryStream;
        if (m != null)
        {                
            sum += (int)m.Length;
        }
    }
    sw.Stop();
    Console.WriteLine("As and null test: {0} : {1}", sum,
                      (long)sw.ElapsedMilliseconds);
}

...结果是这样的:

As and null test: 0 : 342

比上面两个代码慢

[编辑]:

按照建议将每个例程交给他们自己的副本...

static void UsingAs(object[] values)
{
    object[] a = values.ToArray();

    Stopwatch sw = Stopwatch.StartNew();
    int sum = 0;
    foreach (object o in a)
    {

        if (o is MemoryStream)
        {
            var m = o as MemoryStream;
            sum += (int)m.Length;
        }
    }
    sw.Stop();
    Console.WriteLine("As: {0} : {1}", sum,
                      (long)sw.ElapsedMilliseconds);
}

static void UsingCast(object[] values)
{
    object[] a = values.ToArray();

    Stopwatch sw = Stopwatch.StartNew();
    int sum = 0;
    foreach (object o in a)
    {
        if (o is MemoryStream)
        {
            var m = (MemoryStream)o;
            sum += (int)m.Length;
        }
    }
    sw.Stop();
    Console.WriteLine("Cast: {0} : {1}", sum,
                      (long)sw.ElapsedMilliseconds);
}

...输出:

Cast: 0 : 282
As: 0 : 282

现在他们有了相同的结果,谢谢 Remus!

独立运行 Cast 和 As,它们也会产生相同的结果(即 282)。现在,至于当他们得到自己的数组副本时,为什么他们变得更快(从 322 减少到 282 毫秒),我无法从中得到任何东西:-)那完全是另一个故事

最佳答案

如果您想排除 L2 缓存和 TLB 未命中的情况,则只需在相同大小的不同 MemoryStream 上调用第二个测试即可。

关于c - 基准测试时如何使缓存无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2680035/

相关文章:

algorithm - 与缓存引用与缓存未命中的比率相比,为什么缓存未命中与指令的比率是缓存性能的更好指标?

caching - 返回 RDD 的 Apache Spark 方法(带尾递归)

swift - UITableView 内存问题

javascript - Node.js 未定义 VS 空字符串内存使用

javascript - 对 Javascript、PHP 和 Dart 进行基准测试

c - 是什么导致我使用 realloc 时出现未定义的行为

c - 为什么我的 openGL 纹理只覆盖了我的四边形的一半?包含来源

c++ - 是否有 webAssembly 的标准基准?

c - 使用循环和指针从文件读入结构

c - 停止进程然后再次使用它而不杀死它