intel指令優化
阿新 • • 發佈:2019-01-10
程式優化
預讀指令讀記憶體
提前預取記憶體中資料到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