QWORD境界にアラインする

intel系プロセッサでは(というか32bitCPUならなんでもそうだとおもうけど)ミスアラインというのがあって、16bit(WORD) 32bit(DWORD)単位でメモリにアクセスするとき、そのアドレスの先頭がWORDなら2の倍数、DWORDなら4の倍数でないと、キャッシュミスでパフォーマンスが落ちる。そこで画像のように固定長かつ大量のデータを扱う時は、メモリ確保の段階で、以下のようなコードを用いて、先頭アドレスを揃える。これを「○○境界へのアライン」と言う。

このコード、頻出パターンらしいんだが、つい最近までこの2行がやってる事がさっぱり理解できなかった^^; 覚え書きとして残しておく。

 // QWORD境界に整合する
 m_pPtr = new BYTE[4 * WIDTH * HEIGHT + 7];
 m_pBits = (void*)( ((int)m_pPtr + 7) & ~7 );

コードの説明

QWORDは64bit(8バイト。ただしこれはマイクロソフト用語で、本来は128bitの事を指す筈)の事。MMX時代にはハードウェアパックド演算とやらで64bit単位で演算するのが流行りだったようだ。まあ、QWORD境界にアラインされていれば、自動的にDWORD境界にもアラインされる(8の倍数は常に4の倍数だから)ので、これは踏襲する事にする。

まずメモリの確保

 m_pPtr = new BYTE[4 * WIDTH * HEIGHT + 7];

画像を配置するためのメモリをバイト単位で取得している。"4"が1ピクセル(R8B8G8A8)でそれの幅×高さ。更に7バイト余分に確保している

次に先頭アドレスをアラインさせる

 m_pBits = (void*)( ((int)m_pPtr + 7) & ~7 );

確保したアドレスm_pPtrに7を足して(=アドレスを7バイト進めて)、7のNOT(つまり11111111 11111111 11111111 11111000)とandを取り、下位3ビットをクリアする。これによりm_pBitsが指すアドレスは確実に8の倍数(=QWORD境界)になる。あらかじめ確保する領域は7バイト余分にとってあるので、この作業によってメモリがリークしたりはしない。


領域をdeleteする時はm_pPtrを解放すればOK