多核编程伪共享问题及其对策

多核编程伪共享问题及其对策

作者: Zhouweiming 周伟明 (42 篇文章) 日期: 三月 26, 2009 在 10:26 上午

多核编程中的伪共享问题及其对策

注:本文主要内容摘自笔者所著的《多核计算与程序设计》一书,略有修改,后续还会继续发布系列文章,如有需要,可以考虑将一下地址加入到您的浏览器收藏夹中:http://software.intel.com/zh-cn/blogs/category/multicore/

前一篇文章 “多核编程锁竞争问题及其对策”中,提到了多核编程所遇到的各种问题,本文就来讲述一种的一个问题,伪共享问题及其对策。

伪共享问题在《多核程序设计技术-通过软件多线程提升性能》一书中有详细讲解,它是由于CPU cache机制造成的,CPU读取Cache时是以行为单位读取的,如果两个硬件线程的两块不同内存位于同一Cache行里,那么当两个硬件线程同时在对各自的内存进行写操作时,将会造成两个硬件线程写同一Cache行的问题,它会引起竞争,就像在乒乓球比赛一样,效率将成百倍的下降。

在单核系统中,伪共享问题是不存在的,因为同一时刻只有一个硬件线程在执行,不存在同时写同一Cache行的问题。

伪共享问题在实际情况中是经常可以碰到的,比如两个线程同时写一个数组的相邻部分,或者写两块相邻的内存,这些都有可能造成伪共享问题。

对于分配的内存,可以采取一定的内存分配算法使各块内存不在同一Cache行里,但对于数组或变量的访问,就必须要由程序员在设计时进行避免伪共享问题。

要解决伪共享问题,首先必须知道给定的内存中,那块区域会处于同一Cache行内,Intel的系统中,有一个简单的算法可以得到一块内存中对应的Cache行首地址,即每个Cache行首地址都是Cache行大小的整数倍。

比如一块内存大小为60字节,首地址为0x0012ff52,由于0x0012ff52除以64以后余数为0x12,因此这个地址不是Cache行的首地址。在这个地址之前的Cache行首地址为0x0012ff40,在这个地址之后的Cache行首地址为0x0012ff80。对应的内存位于两块不同的Cache中。如下图所示:

 

图1:Cache行对齐示意图

根据上面所说的Cache行首地址为Cache行大小的整数倍的特点,可以设计一个函数来取出给定地址之后的第0个Cache行首地址。代码如下:

/**  计算给定地址之后的第0个Cache行首地址

    如果给定地址刚好为一个Cache行首地址,那么计算结果等于它自身

    @param    void *pAddr - 给定的地址   

    @return   void * - 返回给定地址之后的第0个Cache行首地址 

*/

void *GetCacheAlignedAddr(void *pAddr)

{

    int  m = CACHE_LINE_SIZE;

    void *pRet = (void *)((UINT(pAddr + m - 1)) & (-m));

    return pRet;

}

取到了Cache行首地址后,就可以区分出两块内存是否在同一Cache行中了,对避免伪共享问题就有了很大的帮助。

如果给定地址刚好等于某个Cache行首地址,但是却想取到的地址是它的下一个Cache行首地址,那么可以用以下函数来获取:

/**  计算给定地址之后的Cache行首地址

如果给定地址刚好为一个Cache行首地址,那么计算结果等于它的下一个Cache行首地址

 

@param   void *pAddr - 给定的地址   

@return  void * - 返回给定地址之后的Cache行首地址 

*/

void *GetNextCacheAlignedAddr(void *pAddr)

{

    int  m = CACHE_LINE_SIZE;

 

    void *pRet = (void *)(((UINT)(pAddr) + m )&(-m));

 

    return pRet;

}

当然,伪共享问题在许多地方都会出现,各种地方的处理方法各有不同,但是所有的方法都需要用到上面讲过的取Cache行首地址的方法。

伪共享问题遇得较多的地方是处理数组类型的数据,其次是内存管理上要从源头上将伪共享问题减少。后续的多核系列文章中,还会有文章详细讲解具体的伪共享处理实例。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值