c# - 数组求和缺失时的预期缓存效果

标签 c# algorithm performance caching cpu-cache

我预计以下程序在性能方面完全受内存限制(数组比 L3 缓存大得多)。

因此,我预计 long 数组的总和花费的时间几乎是 int 数组总和的两倍。

但它们几乎花费相同的时间:

 int sum took 81 ms, result = 4999999950000000
long sum took 87 ms, result = 4999999950000000

谁能解释一下吗?

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

namespace MemoryPerformance
{
    class Program
    {
        static void Main(string[] args)
        {
            const int count = 100_000_000;
            int[] intArray = Enumerable.Range(0, count).ToArray();
            long[] longArray = intArray.Select(x => (long)x).ToArray();
            Measure(() => intSum(intArray), " int sum");
            Measure(() => longSum(longArray), "long sum");
        }

        static long intSum(int[] array)
        {
            long sum = 0;
            for (int i = 0; i < array.Length; i++) sum += array[i];
            return sum;
        }

        static long longSum(long[] array)
        {
            long sum = 0;
            for (int i = 0; i < array.Length; i++) sum += array[i];
            return sum;
        }

        static void Measure(Func<long> calc, string description)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            long sum = calc();
            stopwatch.Stop();
            Console.WriteLine($"{description} took {stopwatch.ElapsedMilliseconds} ms, result = {sum}");
        }
    }
}

最佳答案

您测量的时间主要是“只是CPU时间”。 如果您只对数字进行求和并省略整个内存访问,如this fork of Harolds answer ,您会发现只需将循环中的所有数字相加所需的时间几乎相同,无需从数组/内存中读取它们:

static long noSum(long[] array)
{
        long sum = 0;
        for (int i = 0; i < array.Length; i ++) sum += i;
        return sum;
}

这意味着,即使 CPU 必须 从内存中获取数据并且无法将其全部保存在缓存中,它也可以非常高效地完成此操作,因为您没有使用随机数组访问:对于循环的情况,它有足够的时间来预取下一个缓存行,同时仍在执行计算。这导致几乎没有等待时间(推测执行任何人?!;-))。因此,对于您的情况并不重要。显然,在您需要更快地访问大量内存的情况下,就像在 Harolds“稀疏”测试用例中一样,它确实如此。

关于c# - 数组求和缺失时的预期缓存效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49116685/

相关文章:

algorithm - 困难的算法 : Optimal Solution to 1

C# Collection<T>.Remove(T item) 尽管对象数据相等但不起作用

c# - 根据静态属性中的列表验证下拉列表选定值

c++ - 在 M X N 矩阵中查找 m x n 子矩阵的最快方法

Ruby 搜索树示例混淆

c# - .NET (C#) 中 64 位应用程序的性能优势

mysql - 在查询中保留不匹配的数据

sql - 使用临时表复制一行的开销值得吗?

c# - 字节数组末尾有大量 0 值

c# - 在 C# 项目中使用伪变量