高速缓冲行

http://blog.sina.com.cn/s/blog_1314fdaf10102uxgg.html
当一个C P U从内存读取一个字节时,它不只是取出一个字节,它要取出足够的字节来填入高速缓存行。高速缓存行可能包含32(老式cpu)、64、128字节,这要根据cpu而定。高速缓存行的作用是为了提高C P U运行的性能。通常情况下,应用程序只能对一组相邻的字节进行处理。如果这些字节在高速缓存中,那么C P U就不必访问内存总线,而访问内存总线需要多得多的时间。
高速缓存行在多处理器系统中引发的问题
cpu1和CPu2读取同一个字节,这将会使该字节和与他相邻的字节读到cpu1和cpu2各自的高速缓存行中;假如cpu1修改了高速缓冲行中字节时,系统会强制cpu1将修改后的字节写回到内存中并且会通知处cpu1以外的cpu2的高速缓冲行作废。当CPU2进行读取数据时会从新读取内存中的字节。
如果CPU1和cpu2不修改字节,再次读取字节时,只会读取自己高速缓冲行的字节,而不会读取内存。

 从上面可以知道,如果多处理器同时读取相同数据将会损伤性能。
引用书上的两段示例代码
读写混放的数据结构(只读与读写的数据放入同一个高速缓存,不好的做法):

 

 

复制代码
struct  CUSTINFO
高速缓冲行
{
   DWORD    dwCustomerID;    
//Mostly read-only
   int      nBalanceDue;     //Read-write
   char     szName[100];     //Mostly read-only
   FILETIME ftLastOrderDate;  //Read-write
}
;
复制代码

 

 

 改版后的结构定义:

 

 

复制代码
//  Determine the cache line size for the host CPU.
// 为各种CPU定义告诉缓存行大小
#ifdef _X86_
#define  CACHE_ALIGN  32
#endif
#ifdef _ALPHA_
#define  CACHE_ALIGN  64
#endif
#ifdef _IA64_
#define  CACHE_ALIGN  ??
#endif

#define  CACHE_PAD(Name, BytesSoFar) \
   BYTE Name[CACHE_ALIGN 
-  ((BytesSoFar)  %  CACHE_ALIGN)]

struct  CUSTINFO
高速缓冲行
{
   DWORD    dwCustomerID;     
// Mostly read-only
   char     szName[100];      // Mostly read-only

   
//Force the following members to be in a different cache line.
   
//这句很关键用一个算出来的Byte来填充空闲的告诉缓存行
   
//如果指定了告诉缓存行的大小可以简写成这样
   
//假设sizeof(DWORD) + 100 = 108;告诉缓存行大小为32
   
//BYTE[12];
   
//作用呢就是强制下面的数据内容与上面数据内容不在同一高速缓存行中。
   CACHE_PAD(bPad1, sizeof(DWORD) + 100);

   
int      nBalanceDue;      // Read-write
   FILETIME ftLastOrderDate;  // Read-write

   
//Force the following structure to be in a different cache line.
   CACHE_PAD(bPad2, sizeof(int+ sizeof(FILETIME));
}
;
复制代码

 

 

 最优的高速缓存行数据问题解决办法就是让一个线程或处理器来访问指定的数据...那对数据的操作就相当于单线程了,这样就可以完全避免高速缓存行问题了。

通过__declspec(align(XXX))来对字段对齐加以控制

糟糕的数据结构设计

改进后的版本

Struct CUSTINFO{

  DWORD dwCustomerID;//只读,经常访问

  int  nBalanceDue;  //读写

  wchar_t szName[100]; //只读,经常访问

  FILETIME ftLstOrderDate; //读写

}

【说明】避免高速缓存行可能出现问题的方法

①使用局部变量或函数参数时,因为他们只让一个线程访问数据,就不会受其他线程影响

②设置线程亲缘性,始终只让一个CPU访问数据。

#define CACHE_ALIGN 64 //64是从LineSize中获取

//强迫每个结构体放在不同的缓存行中

struct __declspec(align(CACHE_ALIGN)) CUSTINFO{

  DWORD dwCustomerID;  //只读,经常访问

  wchar_t szName[100]; //只读,经常访问

  //将以下两个字段放在不同的缓存行中

  __declspec(align(CACHE_ALIGN))

  int  nBalanceDue;  //读写

  FILETIME ftLstOrderDate; //读写

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值