星期四, 五月 05, 2011

What every programmer should know about memory 阅读笔记(6.3)

http://lwn.net/Articles/255364/
6.3 Prefetching
6.3.1 Hardware Prefetching
两次或者更多次的cache miss才会引起prefetch 因为CPU有随机访问引起cache miss的情况 比如访问一个全局变量
如果这样也prefetch会影响效率
一个CPU中会有多个prefetch unit进行prefetch 高级的cache的unit可能多个core共享
prefetch不能越过一个页 因为可能引起page fault或者fetch一个并不需要的页
在不需要的时候引起prefetch 需要调整程序结构才能解决 在指令中插入未定义指令是一种解决方法
体系结构提供全部或者部分关闭prefetch


6.3.2 Software Prefetching
#include <xmmintrin.h>
enum _mm_hint
{
_MM_HINT_T0 = 3,
_MM_HINT_T1 = 2,
_MM_HINT_T2 = 1,
_MM_HINT_NTA = 0
};
void _mm_prefetch(void *p, enum _mm_hint h);
x86系列可用上面函数生成prefetch指令
_MM_HINT_T0 = 3, _MM_HINT_T1 = 2, _MM_HINT_T2 = 1, 就是将内存取到1 2 3级cache
要注意第一每个芯片可能对其实现不同 第二 一般使用MM_HINT_T0 但是如果数据量较大可用另两个选项
_MM_HINT_NTA的NTA是non-temporal access(原文在这里写错了)的缩写 当使用这个选项的时候 数据将被装入l1
但是当这个cache要装入其他数据的时候 原来的数据将不会被存入更高级别的cache 如果有需要数据还要直接写入内存
注意如果数据量很大不要使用这个选项
AMD的CPU提供一种特殊的prefetch指令
直接在程序中增加prefetch代码可能起到作用不大 建议方法是用performance counters查询程序的cache
misses信息 在需要的位置插入prefetch指令
-fprefetch-loop-arrays是GCC提供的编译选项 其将为优化数组循环插入prefetch指令 但是这个选项要小心使用


6.3.3 Special Kind of Prefetch: Speculation
介绍了IA64下提高乱序执行的Speculative loads
其基本思路是当一个load指令和后面的指令关联 造成无法OOO的时候 将load换成Speculative loads
其在有关联的时候不会生效 这样即使指令关联也可OOO


6.3.4 Helper Threads
在当前程序中同时做prefetch会增加程序复杂度 而且可能引起l1i的性能问题
可以单独创建一个线程做prefetch 这个线程要跟执行线程在同一core不同的硬线程 这样他们的l2 cache就是共享的
cpu_set_t self; NUMA_cpu_self_current_mask(sizeof(self), &self);
cpu_set_t hts; NUMA_cpu_level_mask(sizeof(hts), &hts, sizeof(self),
&self, 1); CPU_XOR(&hts, &hts, &self);
这个函数可用来取得cache共享的信息


6.3.5 Direct Cache Access
有一种cache miss是由输入数据造成的 现在的网卡等设备为了提高输入数据的速度都支DMA 数据会不通过CPU直接写入内存
但是这个方式有个问题 有些输入的数据很快就会被CPU处理 比如网卡接到的数据需要被分析类型 这就会产生cache miss影响处理速度
所以INTEL在他们的芯片中增加了DCA功能 其扩展了网卡到内存控制器的协议 在其中传输数据的时候可以增加DCA标志
当CPU从FSB中看到有DCA标志的数据的时候 其将把这个数据写入CACHE(当然CPU也可以根据情况乎略DCA)
这样就减少了之后CPU处理数据时候的cache miss

0 Comments:

发表评论

<< Home