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

作者: 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中。如下图所示:

 

1Cache行对齐示意图

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

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

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

    @param    void *pAddr - 给定的地址   

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

*/

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行首地址的方法。

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

 

参考文献:

【1】          Capi开源项目,链接:http://gforge.osdn.net.cn/projects/capi  

【2】          Intel Thread Building BlockTBB)源代码, http://www.threadingbuildingblocks.org/

【3】          Shameem Akhter, Jason Roberts,“多核程序设计技术-通过软件多线程提升性能”,李宝峰等译,电子工业出版社,2007.03.

【4】          周伟明,“多核编程文章汇总”,http://blog.csdn.net/drzhouweiming/archive/2009/03/24/4019792.aspx

【5】          周伟明,“多核编程中的锁竞争问题及其对策”,http://software.intel.com/zh-cn/blogs/2009/03/26/400001180/

【6】          周伟明,“多核计算与程序设计”,华中科技大学出版社,2009.03.

 

分类: 博客征文专栏, 并行计算

如需了解英特尔软件产品相关的性能和优化选项,请参阅优化注意事项.

 评论 (0)

 引用 (19)


 写评论  

欲获得技术支持,请访问软件支持页面.
姓名 (必填)*

电子邮件 (必填,不在本页面显示)*

您的 URL (可选)


评论*