18(SIMD)

在優化的層次中,從上到下依次是,業務級,算法級,編碼級,指令級,平臺級,和硬件級。

業務級表示很多優化可以在業務討論中被剪枝或者改進,例如業務真的需要用3個月的數據來做分析嗎?還是2個月就夠了?這需要產品經理,技術經理的經驗,不在話下。

算法級主要集中在複雜度上,一個好的複雜度算法,哪怕實現的在拙劣可能都要遠遠好於一個優化到極致的差方法。往往大公司考試喜歡涉及這些方面。

編碼級主要集中在語言上,語言使用的技巧,這方面的技巧非常多,也有很多書,C++編程思想等等。

指令級主要涉及到彙編和特定的處理器,這也有很多技巧,但需要一些低層的經驗,本系列主要覆蓋這個層次,也是比較冷門的層次。

平臺級主要特指linux kernel的一些優化,將kernel優化到一些特定的應用上。

硬件級主要涉及具體的硬件,以及硬件的組合。

優秀的優化工程師需要兼顧從業務級到硬件級的各種知識,這樣的人才非常寶貴。

上面是一些引子,本文繼續討論優化技巧,SIMD,單指令多數據,其簡單含義就是將多個數據進行打包,用一條指令來完成多個數據的計算,和往常一樣,還是舉一個具體的例子。這是我最近優化的例子,可以說是第一個從現實而來的例子,此前的都是和我工作無關的。

簡單解釋一下這個函數的作用,code表示壓縮後的編碼,data中每個數都是0或者1,例如data【0】=0,data【1】=1,這是函數調用的先驗假定,n是需要pack的數量,這裡默認為128,其功能是將data[i](i=0-127)打包成一個4個整形(128bit)。

例如int data[128]={0,1,0.......0,1,1},

調用完PACK1(code,data,128)後

code[0]=3

code[1]=0

code[2]=0

code[3]=1073741824

將code按比特從高到低展開為

[01000000 00000000 00000000 00000000]

[00000000 00000000 00000000 00000000]

[00000000 00000000 00000000 00000000]

[00000000 00000000 00000000 00000011]

原來data為1284=512字節。打包後只有44=16字節。

好,這個功能,應該講清楚了,下面就是實現的代碼,希望感興趣的朋友動手實踐,詳細的代碼分析,下回再說。還會介紹另外一種實現方法,以及指令集兼容的問題,希望讀者持續關注。

#define dolaf3(x,y,z,o,p) "pxor %%xmm1,%%xmm1/npxor %%xmm2,%%xmm2/npxor %%xmm3,%%xmm3/npxor %%xmm4,%%xmm4/nmovhpd "#x"(%1),%%xmm1/npsllq $32,%%xmm1/nmovhpd "#y"(%1)
,%%xmm2/npsllq  $32,%%xmm2/npsrlq  $32,%%xmm2/nORPD %%xmm1,%%xmm2/nmovss "#z"(%1),%%xmm3/npsllq  $32,%%xmm3/nmovss "#o"(%1),%%xmm4/nORPD  %%xmm3,%%xmm4/npslld $"#p"
,%%xmm15/nORPD   %%xmm2,%%xmm15/nORPD   %%xmm4,%%xmm15/n"
#define laf3(x) dolaf3(x*4,128+x*4,256+x*4,384+x*4,1)

void PACK1(uint32_t* code,uint32_t* data,size_t n)
{
        unsigned char* des = (unsigned char*)code;
        unsigned char* src = (unsigned char*)data;
        for(int i =0,j=0;j<n;src+=4*4,des+=128*4,j+=128)
        {
          __asm__ __volatile__(
                "pxor %%xmm15,%%xmm15/n"
                laf3(0)
                laf3(1)
                laf3(2)
                laf3(3)
                laf3(4)
                laf3(5)
                laf3(6)
                laf3(7)
                laf3(8)
                laf3(9)
                laf3(10)
                laf3(11)
                laf3(12)
                laf3(13)
                laf3(14)
                laf3(15)
                laf3(16)
                laf3(17)
                laf3(18)
                laf3(19)
                laf3(20)
                laf3(21)
                laf3(22)
                laf3(23)
                laf3(24)
                laf3(25)
                laf3(26)
                laf3(27)
                laf3(28)
                laf3(29)
                laf3(30)
                laf3(31)
                "movdqu  %%xmm15 ,(%0)/n"
                ::"r"(des),"r"(src):"memory");
        }
        __asm__ __volatile__ (
                " sfence /n "
                ::
        );
};