What every programmer should know about memory 阅读笔记(6.3)
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