c++ - 有效计算大型 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
问题是不按顺序访问内存会产生很多缓存未命中,在内存方面有没有更好的方法来解决这个问题?提前对数组进行整形也存在内存效率低下的问题。
谢谢。
解决方案
一种简单的解决方案是遍历连续维度。但是,如果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)。
推荐阅读
- macos - 使用光标在屏幕上显示 iTerm [或活动屏幕]
- flutter - 颤振:DateFormat.parse 仅在桌面 Win32 上在午夜返回错误时间
- sql - AWS Athena 列无法解决
- python-3.x - 将多个图像读取为块
- ruby - 更新后在 Watir 中设置默认下载目录的问题
- c - 创建 const C 结构并将其从 Swift 传递回 ObjC 的最有效方法是什么?
- python - 索引(x 轴)作为 datetime64[ns] 不起作用
- regex - 使用正则表达式后无法排序列表
- ansible - Ansible:在多行字符串中使用换行符
- c# - 使用字典动态序列化具有属性的 Json 对象