除了通过编译器选项来使用软件预取之外,也可以通过prefectch directive来来告诉在访问某些内存时是否进行软件预取;
(1)#pragma noprefetch 指示编译器不进行软件预取
(2)#pragma prefetch指示编译器进行软件预取
(3)#pragma prefetch a,b,指示编译器对于变量a,b的访问进行软件预取。
#pragma noprefetch b
#pragma prefetch a
for(i=0;i
上面的循环中通过表达式a[j]访问数组,编译器会插入软件预取指令来把a[j+d]加载进缓存中,其中d由编译器分析后决定。
还可以通过SSE Intrinsics来支持软件预取,当然,这必须是在支持SSE扩展的处理器上才发挥作用;
void _mm_prefetch(char const *a,int sel);
它对应着PREFETCH指令,告诉处理器把地址a对应的缓存加载到更高速的缓存中,sel给出了预取操作的类型,如下所示:
PREFETCHINTA _MM_HINT_NTA 采用非临时预取,减少缓存行的污染
PREFETCH0 _MM_HINT_T0 预取数据到所有缓存
PREFETCH1 _MM_HINT_T1 预取到L2,L3缓存,但是不到L1缓存
PREFETCH2 _MM_HINT_T2 仅预取数据到L3缓存
如果预取的数据仅仅使用一次,一般应该采用非临时预取,如果要进行写操作或者访问该缓存行多次,一般采用预取数据到所有缓存。
for(i=0;i
_mm_prefetch((char *)&arrar[i+2048],_MM_HNT_T0);
}
Func(&array[i]);
}
上面这个循环,由于步长太大,硬件自动预取无法有效工作。而通过软件预取则可以完成数据预取到缓存行的功能。