📜  计算机组织 |局部性和缓存友好代码(1)

📅  最后修改于: 2023-12-03 15:12:03.915000             🧑  作者: Mango

计算机组织 | 局部性和缓存友好代码

在编写代码时,需要注意其对计算机组织的影响,特别是CPU缓存的利用。优秀的代码应具有局部性和缓存友好的特点,以提高程序的运行效率。

局部性

局部性是指程序在执行某个指令时,其周围的指令、数据和变量很可能也会在近期内被使用。因此,计算机系统利用局部性原理来加速程序执行。

时间局部性

时间局部性指在一段时间内,程序很可能会重复使用相同的指令、数据和变量。因此,CPU缓存将最近使用的内容缓存起来,以加速程序的执行。

空间局部性

空间局部性指程序访问内存时,通常会访问相邻的内存单元。因此,CPU缓存将连续的内存块缓存起来,以加速程序的执行。

命中率

缓存命中率是指CPU缓存中所缓存的数据、指令的使用频率与程序实际使用的数据、指令的比率。命中率越高,程序执行效率越高。

缓存友好代码

为了利用计算机的局部性,编写缓存友好的代码是非常重要的。以下是一些编写缓存友好代码的技巧:

数据对齐

在访问内存时,如果数据结构被对齐到缓存块边界,可以实现更快的访问速度。因此,程序员应该为重要的数据结构进行对齐。

循环展开

循环展开将循环中的多个语句独立开来,从而减少了程序进行跳转的次数,提高了程序的局部性。

for(int i=0;i<N;i++){
    a[i] = b[i]*c[i];
}

展开后:

for(int i=0;i<N;i+=4){
    a[i] = b[i]*c[i];
    a[i+1] = b[i+1]*c[i+1];
    a[i+2] = b[i+2]*c[i+2];
    a[i+3] = b[i+3]*c[i+3];
}
矩阵变换

矩阵变换可以避免访问大量的内存单元,从而提高程序的局部性。

for(int i=0;i<N;i++){
    for(int j=0;j<N;j++){
        c[i][j] = a[i][j] + b[i][j];
    }
}

变换后:

for(int i=0;i<N;i+=4){
    for(int j=0;j<N;j+=4){
        c[i][j] = a[i][j] + b[i][j];
        c[i][j+1] = a[i][j+1] + b[i][j+1];
        c[i][j+2] = a[i][j+2] + b[i][j+2];
        c[i][j+3] = a[i][j+3] + b[i][j+3];
        
        c[i+1][j] = a[i+1][j] + b[i+1][j];
        c[i+1][j+1] = a[i+1][j+1] + b[i+1][j+1];
        c[i+1][j+2] = a[i+1][j+2] + b[i+1][j+2];
        c[i+1][j+3] = a[i+1][j+3] + b[i+1][j+3];
        
        c[i+2][j] = a[i+2][j] + b[i+2][j];
        c[i+2][j+1] = a[i+2][j+1] + b[i+2][j+1];
        c[i+2][j+2] = a[i+2][j+2] + b[i+2][j+2];
        c[i+2][j+3] = a[i+2][j+3] + b[i+2][j+3];
        
        c[i+3][j] = a[i+3][j] + b[i+3][j];
        c[i+3][j+1] = a[i+3][j+1] + b[i+3][j+1];
        c[i+3][j+2] = a[i+3][j+2] + b[i+3][j+2];
        c[i+3][j+3] = a[i+3][j+3] + b[i+3][j+3];
    }
}
总结

为了使程序能够充分利用CPU缓存和局部性原理,程序员需要编写缓存友好的代码。上述技巧只是其中的一部分,在实际编程中需要根据具体情况综合运用。