有時候為了加快大量數(shù)據(jù)的存取操作,我優(yōu)化了重要路徑上的算法,用盡了精簡代碼的技巧,還采用處理指令矢量化的技能,為程序定制了一個內(nèi)存管理器以增加程序的緩沖友好性(cache friendly),一般情況下是可以達到最終目的了,可在圖像處理相關(guān)的代碼中,竟然發(fā)現(xiàn)最大優(yōu)化機會在地址訪問上,比如本人曾經(jīng)見過這樣的source code:
? typedef unsigned Pixel32;
? struct Pixel24 { u8 r, g, b; };

? Pixel24* pRaw = new Pixel24[width*height];
??Pixel32* pSrcImg = loadFromFile("tangent.bmp");
? fillPort(pRaw, dstRt, pSrcImg, srcRt);???// 這個函數(shù)的內(nèi)部實現(xiàn)對于32bit pixel -> 24bit pixel比較麻煩哦

我知道,典型的IA32系的處理器的尋址操作在機器字的n倍處最快的。
C++中:
? int a;
??Obj x;
的代碼產(chǎn)生的訪問對象的地址由編譯器完成了!而且絕對保證以最快地方式訪問;
?而 Obj* x;
??????Pixel24* pRaw = new Pixel24[sizeof(Pixel24)*width*height];
????? Pixel32* pSrcImg = ....
的pRaw, pSrcImg就隨運行時而定,不一定在“機器字的n倍處”,而且其一部分數(shù)據(jù)在“機器字的n倍處”。

可想而知,32bit的像素在memory上很容得以地址對齊,但是也可能其首地址沒有在機器字的n倍處,可24bit就更麻煩了。


所以我的策略是:動態(tài)分配時,多分配一個機器字的空間,然后想個辦法讓Pointer定在這個分配的線性空間內(nèi)的首個“機器字的n倍處”,之后的對象訪問對齊問題靠padding完成(不過,這一步只有在真的需要時才作,因為會有大量空間浪費!)。


這里給出了me的對齊code:

?
template <typename Pointer, int Align =4>
? Pointer alignAddress(void* raw)
? { // 把raw對齊為機器字的整數(shù)倍,Align為機器字的字節(jié)數(shù).(需要在raw處多分配align個字節(jié))
??? // Align默認為4,即32bit機的地址對齊
??? Pointer p = reinterpret_cast<Pointer>(
????? (reinterpret_cast<uintptr_t>(raw) + Align-1) & ~(Align-1) );???// 這里有點技巧
??? return p;
? }

就這么點。

可以這樣使用:
??????#define ALIGN_SET 4
??????Pixel24* pT = new unsigned char[sizeof(Pixel24)*width*height + ALIGN_SET];
????? Pixel24* pRaw = alignAddress<Pixel24*, ALIGN_SET>(pT);
????? // pRaw就是所要的地址,需要時對Pixel24開啟編譯器padding選項

????? 有了這樣的保證,前面的fillPort的優(yōu)化工作就更容易了!