如何在高速缓存边界对齐数据结构
原文地址:http://intel.csdn.net/ISN_J.aspx?action=JMP&pointid=396
挑战
确保每个同步变量都独自位于一个高速缓存行上。 正如我们在如何避免错误共享 中所讨论的那样,当将同步结构拉伸至高速缓存行的大小后,必须确保同步结构在高速缓存边界上对齐。
解决方案
利用下面给出的适当编码技术,将数据结构在高速缓存边界上对齐。 将同步结构拉伸为高速缓存行的大小并不能说是完全大功告成。您还需确保同步结构在高速缓存边界上对齐。同步变量不能与另一个同步结构位于相同的高速缓存行上,如果同步结构没有在高速缓存边界上对齐,则同步变量无法独自位于一个高速缓存行上。可以采用下面两种技术中的一种来执行对齐。
针对动态内存,采用如下代码片断:
struct syn_str { int s_variable; };
void *p = malloc ( sizeof (struct syn_str) + 127 );
syn_str * align_p = (syn_str *)( (((int) p) + 127) & -128 );
当使用英特尔 C/C++ 编译器时,也可采用下面的代码片断:
_declspec(align(128)) struct syn_str aligned_structure;
问题点数:100、回复次数:6Top
1 楼DentistryDoctor(不在无聊中无奈,就在沉默中变态)回复于 2006-08-25 20:29:58 得分 10
学习Top
2 楼nkwesley(江南丝竹)回复于 2006-08-30 09:07:57 得分 0
好深奥啊Top
3 楼lishidong(软件开发者)回复于 2006-09-15 17:04:44 得分 0
谢谢Top
4 楼rickfeng(VC菜鸟)回复于 2006-09-28 13:38:20 得分 20
问一下,边界对齐的好处是什么?提升性能吗?Top
5 楼mathe()回复于 2006-09-28 16:31:17 得分 50
SSE, MMX等指令都需要内存对齐。
对于普通代码,内存边界对齐也是有好处的,可以降低高速缓存(Cache)和内存交换数据的次数。
主要问题是在于Cache本身是分成很多Cache-Line,每条Cache-Line具有一定的长度,比如一般来说L1 Cache每条Cache Line长度在32个字节或64个字节;而L2的会更大,比如64个字节或128个字节。
用户每次访问地址空间中一个变量,如果不在Cache当中,那么就需要从内存中先将数据调入Cache中。
比如现在有个变量 int x;占用4个字节,它的起始地址是0x1234567F;那么它占用的内存范围就在
0x1234567F-0x12345682之间。如果现在Cache Line长度为32个字节,那么每次内存同Cache进行数据交换时,都必须取起始地址时32(0x20)倍数的内存位置开始的一段长度为32的内存同Cache Line进行交换.
比如0x1234567F落在范围0x12345660~0x1234567F上,但是0x12345680~0x12345682落在范围0x12345680~0x1234569F上,也就是说,为了将4个字节的整数变量0x1234567F~0x12345682装入Cache,我们必须调入两条Cache Line的数据。但是如果int x的起始地址按4的倍数对齐,比如是
0x1234567C~0x1234567F,那么必然会落在一条Cache Line上,所以每次访问变量x就最多只需要装入一条Cache Line的数据了。比如现在一般的malloc()函数,返回的内存地址会已经是8字节对齐的,这个就是为了能够让大部分程序有更好的性能。
而对于SSE,SSE2,MMX等,经常需要处理长度为32字节,64字节,128字节的数据;同样,将这些内存块的起始地址按对样长度对齐,可以减少访问Cache Line的次数。Top
6 楼guinh3()回复于 2006-10-04 21:59:54 得分 20
这个技术很使用,在我们的项目中需要使用很大的动态Double数组,而后进行计算,地址和Cache是否对其很重要,假如第一个不对齐,那后面的很多就会错位,那很明显算法的效率就会下降。Top




