C/C++串行程序优化:提高内存读写效率

操作系统使得计算机硬件对程序员透明,即程序员在写代码时不用考虑机器到底如何工作。但是了解CPU内高速缓存的作用能帮助程序员设计出更高效的代码。下面简单介绍一下CPU内的高速缓存和程序优化方法

CPU的高速缓存

计算机中CPU的工作频率(2-4GHz)高于内存的工作频率(1-2GHz)。

但是程序运行时CPU需要从内存中不断读入数据,如果CPU直接从内存中读数据,需要保持和内存同样的频率,会大大损失CPU的性能。CPU内部的高速缓存(SDRAM)就是为了解决这个问题而设计的一个很小的高速缓存区,CPU可以快速地从高速缓存中读取数据,而高速缓存则以较慢的速度批量读取内存中的数据,这样可降低CPU性能的损失。但如果高速缓存中没有CPU需要的数据,高速缓存就要再从内存中读一次数据。

因此如果高速缓存每次从内存中读取的数据被CPU利用率(CPU的命中率)越大,那么CPU做同样次数运算高速缓存从内存中读取数据的次数越少,数据读取消耗时间越少,CPU的性能降低越小;反之高速缓存从内存读取数据的次数越多,数据读取消耗时间越多,CPU性能降低越大。

优化程序的内存读取

因此要使得程序效率提高,就需要让CPU的命中率越大。通常高速缓存从内存中读取数据为连续读取。我们可以比较下面两段代码:

for(unsigned int i = 0; i < n; ++i) {
    for (unsigned int k = 0; k < n; ++k) {
        for (unsigned int j = 0; j < n; ++j) {
            A[i*n + j] += B[i*n + k] * C[k*n + j];
            //每次对最内层j循环CPU访问内存B[i*n+k]不变,A[i*n+j]和C[k*n+j]为连续的内存
        }
    }
}

for(unsigned int i = 0; i < n; ++i) {
    for (unsigned int j = 0; j < n; ++j) {
        for (unsigned int k = 0; k < n; ++k) {
            A[i*n + j] += B[i*n + k] * C[k*n + j];
            //每次对最内层k循环CPU访问内存A[i*n+j]不变,B[i*n+k]为连续的内存,C[k*n+j]为离散的内存
        }
    }
}

这是一个矩阵相乘的代码。上面一段代码j的循环在最里层,k的循环在中间层;下面一段代码k的循环在最里层,j的循环在中间层。

我们发现总是上面的代码运行速度要快一些。因为当j在循环最里层时,可以在n次计算里CPU每次计算仅j不同,CPU只用访问C的一段连续内存。而当k在循环最里层时,CPU不仅要访问B的一段连续内存,还要访问C的不连续内存。因此上面的代码的CPU命中率要高于下面的代码。下面的代码比上面的代码在内存读取上要多花一些时间,使得运行时间增长。

总结

要提高程序内存读写的效率,因为有高速缓存的存在,我们需要提高CPU的命中率,这需要在程序中尽可能地让CPU连续地访问内存,尽量避免跳跃地访问内存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值