程序优化
预读指令读内存
提前预取内存中数据到CACHE内,提高CACHE的命中率,加速内存读取速度,这是设计预读指令的主要目的。
prefetch0、prefetch1、prefetch2、 prefetchnta。
预取指令只是给CPU一个提示,所以它可被CPU忽略,而且就算预取一段错误的地址也不会导致CPU异常。一般使用prefetchnta预取指令,因为它不会污染CACHE,它把每次取得的数据都存放到L2 CACHE的第一条CACHE LINE(不同的cpu不一样 ),而另外几条指令会替换CACHE中最近最少使用的CACHE LINE。
非暂时移动指令写内存
我们知道为了保证CACHE与内存之间的数据一致性,CPU对CACHE的写操作主要有两种方式同步到内存,写透式(Write Through)和写回式(Write-back)。不管哪种同步方式都是要消耗性能的,而在某些情况下,写CACHE是不必要的:
有哪些情况不需要写CACHE呢?比如做数据拷贝(高效memcpy函数实现)时,或者我们已经知道写的数据在最近一段时间内(或者永远)都不会再使用了,那么此时就可以不用写CACHE,让对应的CACHE LINE自动失效,以便缓存其它数据。这在某些特殊场景非常有用,相应的汇编指令有movntq、movntsd、movntss、movntps、movntpd、movntdq、movntdqa。
完整的利用预读指令和非暂时移动指令实现的高速内存拷贝函数。
void X_aligned_memcpy_sse2(void* dest, const void* src, const unsigned long size_t)
{
__asm
{
mov esi, src; //src pointer
mov edi, dest; //dest pointer
mov ebx, size_t; //ebx is our counter
shr ebx, 7; //divide by 128 (8 * 128bit registers)
loop_copy:
prefetchnta 128[ESI]; //SSE2 prefetch
prefetchnta 160[ESI];
prefetchnta 192[ESI];
prefetchnta 224[ESI];
movdqa xmm0, 0[ESI]; //move data from src to registers
movdqa xmm1, 16[ESI];
movdqa xmm2, 32[ESI];
movdqa xmm3, 48[ESI];
movdqa xmm4, 64[ESI];
movdqa xmm5, 80[ESI];
movdqa xmm6, 96[ESI];
movdqa xmm7, 112[ESI];
movntdq 0[EDI], xmm0; //move data from registers to dest
movntdq 16[EDI], xmm1;
movntdq 32[EDI], xmm2;
movntdq 48[EDI], xmm3;
movntdq 64[EDI], xmm4;
movntdq 80[EDI], xmm5;
movntdq 96[EDI], xmm6;
movntdq 112[EDI], xmm7;
add esi, 128;
add edi, 128;
dec ebx;
jnz loop_copy; //loop please
loop_copy_end:
}
}
参考:我的第一份实习工作师父的博客 youfu blog