CPU缓存体系对Go程序的影响

小菜刀最近在medium上阅读了一篇高赞文章《Go and CPU Caches》,其地址为https://teivah.medium.com/go-and-cpu-caches-af5d32cc5592,感觉收获颇多。小菜刀在该文章的基础上做了些修改和扩展,整理出来分享给读者朋友们。

CPU缓存体系

现代计算机处理器架构多数采用对称多处理系统(Symmetric multiprocessing system,SMS)。在这个系统中,每一个核心都当成是独立的处理器,多处理器被连接到同一个共享的主存上,并由单一操作系统来控制。

为了加速内存访问,处理器有着不同级别的缓存,分别是 L1、L2 和 L3。确切的体系结构可能因供应商、处理器模型等而异。目前最常见的架构是把 L1 和 L2 缓存内嵌在 CPU 核心本地,而把 L3 缓存设计成跨核心共享。

在这里插入图片描述

一个CPU通常包含多个核心,每个CPU核心拥有L1 Cache和 L2 Cache,在L1 Cache中又分为dCache(数据缓存)和iCache(指令缓存),同时多核心共享L3 Cache。

越靠近CPU核心的缓存,其容量越小,但是访问延迟越低。

在这里插入图片描述

当然,这些具体的数字会因处理器模型而异。不过,可以得出明显的结论就是,处理器访问L1缓存的速度远远快过直接访问主存,它们至少相差数十倍

CPU从主存中读取数据至Cache时,并非单个字节形式进行读取,而是以连续内存块的方式进行拷贝,拷贝块内存的单元被称为缓存行(Cache Line)。这样做的理论依据是著名的局部性原理

时间局部性(temporal locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。

空间局部性(spatial locality):在最近的将来将用到的信息很可能与现在正在使用的信息在空间地址上是临近的。

L1的缓存行大小一般是64字节, L2和L3高速缓存行的大小大于或等于L1高速缓存行大小,通常不超过L1高速缓存行大小的两倍。同时,L2和L3高速缓存的高速缓存行需要小于内存页(一般是4kb)。

以小菜刀的电脑为例,以下是系统报告

在这里插入图片描述

但是,这里没有展示出L1 Cache及其缓存行的大小,我们可通过以下命令方式获取,得知本机的缓存行大小为64字节。

$ sysctl -a | egrep 'cachesize|cachelinesize'
hw.cachesize: 8589934592 32768 262144 6291456 0 0 0 0 0 0
hw.cachelinesize: 64
hw.l1icachesize: 32768
hw.l1dcachesize: 32768
hw.l2cachesize: 262144
hw.l3cachesize: 6291456

这意味着,如果处理器需要拷贝一个int64类型组成的Go切片到缓存中时,它会单次一起拷贝8个元素,而不是单个拷贝。如果我们的程序能让数据是以连续内存的方式存储(例如数组),这样当处理器访问数据元素时,缓存命中率就会很高。通过减少从内存中读取数据的频率,从而提高程序的性能。

缓存行在Go程序中的具体应用

来看一个具体的例子,该例为我们展示了利用CPU缓存带来的好处。

func createMatrix(size int) [][]int64 {
   
	matrix := make([][]int64, size)
	for i := 0; i < size; i++ {
   
		matrix[i] = make([]int64, size)
	}
	return matrix
}

const matrixLength = 6400

func BenchmarkMatrixCombination(b *testing.B) {
   
	matrixA := createMatrix(matrixLength)
	matrixB := createMatrix(matrixLength)

	for n := 0; n < b.N; n++ {
   
		for i := 0; i < matrixLength; i++ {
   
			for j := 0; j < matrixLength; j++ {
   
				matrixA[i][j] = matrixA[i][j] + matrixB[i
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值