问题描述
正在使用cpu缓存首选的连续缓冲区吗?
我正在尝试编写一个对图像执行多项操作的应用程序(一些非常局部的操作,例如移位,导数,以及一些结果之间的操作,例如减法)。 我为结果留了一个大缓冲区(每次计算都具有图像的形状,因此我从分配X *图像形状字节开始)
我该怎么做才能最大化cpu缓存命中率?
解决方法
当然,对连续数组进行操作更有可能命中缓存。
您可能需要连续排列数据:
例如:
#include <iostream>
#include <cstdint>
const int SIZE = 3;
int main(){
uint8_t buffer_2d[SIZE][SIZE];
uint8_t* buffer_1d = reinterpret_cast<uint8_t*>(buffer_2d); // or just do uint8_t buffer_1d[SIZE*SIZE];
const auto base = &(buffer_2d[0][0]);
for (int y=0;y<SIZE;++y){
for (int x=0;x<SIZE;++x){
std::cout << "x: " << x << " y: " << y << " offset for [x][y]: " << &(buffer_2d[x][y]) - base << " offset for [y][x]: " << &(buffer_2d[y][x]) - &(buffer_2d[0][0]) << " offset for [y*SIZE+x]: " << &(buffer_1d[y*SIZE+x]) - base << std::endl;
}
}
return 0;
}
将数组作为人为自然的[x][y]
数组进行处理将是无效的,因为数据不是以这种方式对齐的,所以有效的方法是使用[y][x]
或将数组作为单个数组处理维数组,并将索引视为y*LINE_SIZE + x
。
这是此测试的输出,准确地表明了这一点:
x: 0 y: 0 offset for [x][y]: 0 offset for [y][x]: 0 offset for [y*SIZE+x]: 0
x: 1 y: 0 offset for [x][y]: 3 offset for [y][x]: 1 offset for [y*SIZE+x]: 1
x: 2 y: 0 offset for [x][y]: 6 offset for [y][x]: 2 offset for [y*SIZE+x]: 2
x: 0 y: 1 offset for [x][y]: 1 offset for [y][x]: 3 offset for [y*SIZE+x]: 3
x: 1 y: 1 offset for [x][y]: 4 offset for [y][x]: 4 offset for [y*SIZE+x]: 4
x: 2 y: 1 offset for [x][y]: 7 offset for [y][x]: 5 offset for [y*SIZE+x]: 5
x: 0 y: 2 offset for [x][y]: 2 offset for [y][x]: 6 offset for [y*SIZE+x]: 6
x: 1 y: 2 offset for [x][y]: 5 offset for [y][x]: 7 offset for [y*SIZE+x]: 7
x: 2 y: 2 offset for [x][y]: 8 offset for [y][x]: 8 offset for [y*SIZE+x]: 8
最后两个结果使用完全相同的语义,第一个结果将让编译器发出计算结果,但性能应相同。
此外,一旦正确地排列了数据,则取决于您对数据的处理方式,您可能希望使用OpenCL或其他东西并利用GPU或SIMD,如果可以用SIMD表示(单指令,则可能会带来显着的性能改进)。多个数据)代码。
,#ifdef _MSC_VER
_declspec(align(64)) unsigned char block_hashfp;
#else
__attribute__((aligned(64))) unsigned char block_hashfp;
#endif
将进入二级缓存