首页 > 代码库 > [原理分析]多核下的缓存块伪共享问题

[原理分析]多核下的缓存块伪共享问题

摘要:

本文主要介绍多核下的缓存块伪共享问题,该问题的存在可能导致的有趣现象:两个核跑一个程序,不如单个核跑该程序来得快。

正文:

1.本文考虑的处理器中每个核私有L1缓存,并且多个核共享L2缓存;L1和L2缓存中的缓存块大小都为64bytes,认为double数据类型在本机器上需要8bytes来表示;

2. 缓存一致性的协议:本文考虑的缓存一致性是基于监听(snoop)的写无效(write invalidate)策略,给个简单的例子来说明该策略:当core 0和core 1读访问L2中的缓存块A时,那么在core0和core1中同时存在缓存块A的两个拷贝;当core0写L1中的缓存块A拷贝时,并且在总线上发消息说:自己修改了A缓存块;那么core1接受到该消息时,就知道自己L1中的缓存块A拷贝不是最新,此时core1就会将自己的缓存块A拷贝置为无效;当core1再次要访问该缓存块时,由于发现无效,就会从外部(比如从core0的L1缓存)读取最新的拷贝。上述的缓存一致性策略就是基于监听的写无效策略。

3. 下面是本文要考虑的程序:

int i, j, m, n;
double y[m];

for(int i=0; i<m; i++)
	for(int j=0; j<n; j++)
		y[i]+=f(i, j);
我们修改上述的代码,使得其可以在两个core上并行执行,修改后的代码中core_count设置为2,具体如下:

int i, j, iter_count;
int m, n, core_count;
double y[m];
iter_count = m/core_count;

//so core 0 does this
for(i=0; i<iter_count; i++)
	for(j=0; j<n; j++)
		y[i]+=f(i,j);

//so core 1 does this;
for(i=iter_count; i<2*iter_count; i++)
	for(j=0; j<n; j++)
		y[i]+=f(i, j);
假设这里的m=8, 一个缓存块的大小为64bytes, 并且一个double需要8个bytes,这样的情况下,所有的y数组元素刚好占用一个缓存块:其中的y[0-3]元素(缓存块前半段)由core0写访问;而其中的y[4-7]数组元素(缓存块后半段)由core1写访问。虽然每个core上运行的代码只对属于自己的那部分y进行操作,但是由于缓存块在core0和core1中都有拷贝;所以产生的现象是每次一个core对自己那部分的y值进行操作时,另外一个core上的缓存拷贝就会被invalid,造成需要重新读取该cache line的情况;因为这里的两个core其实都不会用到对方的数据,但是实际运行中却会相互影响,使得对方的缓存拷贝无效化,对方要用到该缓存拷贝中的数据时,又需要重新进行读取;由于读取缓存块的时间极大地滞后于处理器计算的速度,因此上述的伪共享会极大影响系统性能:造成两个核的处理速度,不如一个核。

结束语:

本文主要介绍多核下的缓存块伪共享问题,该问题的存在可能导致的有趣现象:两个核跑一个程序,不如单个核跑该程序来得快。


[原理分析]多核下的缓存块伪共享问题