const sumvec = (v) => {
let i,sum = 0
for (i = 0; i < v.length; i++ ){
sum += v[i]
}
return sum
}
我们来看下这个函数是不是「高速缓存」友好的?
首先,对于局部变量 i 和 sum,因为它们都是局部变量,编译器会把它们缓存在寄存器文件中,也就是存储器层次结构的最高层中,因此,就时间局部性而言,循环体内具有良好的性能。
而对于步长为 1 的引用,它对高速缓存友好。假设每个字 是 4 字节,高速缓存块的大小也是 4 个字节,考虑到第一次高速缓存初始为空(冷高速缓存)中,我们可以得出以下命中和不命中的模式:
对局部变量的反复引用是好的,因为编译器能够将它们缓存在寄存器文件中,会显著提高访问速度,这是时间的局部性。 步长为 1 的引用模式是好的,存储器的缓存是将数据存储为连续的块,减少了缓存不命中的概率,这是空间局部性。
const array = [
[1, 2, 3],
[4, 5, 6]
];
const sumArrayRows = (arr) => {
let sum = 0;
const M = arr.length;
const N = arr[0].length;
for (let i = 0; i < M; i++) {
for (let j = 0; j < N; j++) {
sum += arr[i][j];
}
}
return sum;
};
const sumArrayCols = (arr) => {
let sum = 0;
const M = arr.length;
const N = arr[0].length;
for (let j = 0; j < N; j++) {
for (let i = 0; i < M; i++) {
sum += arr[i][j];
}
}
return sum;
};
优秀的程序员将注意力集中在内循环上,因为内循环中的大部分操作和数据访问会对程序的性能产生重大影响; 通过使用步长为 1 的数据访问模式,最大限度地发挥空间局部性的优势,将连续的数据块加载到高速缓存中,从而降低缓存不命中的概率。 充分利用从存储器中读取的数据对象,以优化时间局部性,减少不必要的数据加载操作,从而提高程序性能。 选择合适的数据结构,避免碎片和内存占用过多,确保数据的存储方式有助于缓存的有效利用; 简化分支逻辑可以减少流水线阻塞和预测失败,有助于保持程序的高效性能。
题图生成:Pixabay
内容优化:ChatGPT
内容来源:《深入理解计算机系统》
原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34533.html