首页 > 解决方案 > 有效计算大型 C++ 数组中的平均值

问题描述

我有一个包含 7 个块的 65K 样本的数据集:float arr[7][65536]我需要计算每个相应 7 个数字的平均值,因此结果将是一个大小为 65536 的数组:

float result[0] = arr[0][0] + arr[1][0] + arr[2][0] + ... / 7
float result[1] = arr[0][1] + arr[1][1] + arr[2][1] + ... / 7

问题是不按顺序访问内存会产生很多缓存未命中,在内存方面有没有更好的方法来解决这个问题?提前对数组进行整形也存在内存效率低下的问题。

谢谢。

标签: c++arraysperformancecaching

解决方案


一种简单的解决方案是遍历连续维度。但是,如果sizeof(arr[0][0])相当大,这可能不是最佳的,因为result不适合 L1 缓存。最佳解决方案可能是使用阻塞来解决这个问题。

这是执行此操作的 C++ 示例代码:

// Blocked reduction using blocks of size 1024
// This loop iterate over the blocks
for(size_t j=0 ; j<65536 ; j+=1024)
{
    for(size_t k=j ; k<j+1024 ; ++k)
        result[k] = arr[0][k];

    // Summation of the current block
    for(size_t i=1 ; i<7 ; ++i)
        for(size_t k=j ; k<j+1024 ; ++k)
            result[k] += arr[i][k];

    for(size_t k=j ; k<j+1024 ; ++k)
        result[k] /= 7;
}

请注意, 的类型result必须足够大,以容纳比 的 小/大 7 倍的值arr[0][0]。这个循环应该由你的编译器向量化,并且应该产生更少的缓存未命中,从而产生更快的代码。

PS:如果循环未矢量化,您可以通过在基于#pragma omp simd内部的循环之前添加 OpenMP 指令来帮助您的编译器k(并确保启用 OpenMP)。


推荐阅读