Pentium4に最適化されたMersenne Twister のソースコードを読む!

私が知る限り国内最速の実装と思われる*1MT法乱数のソースコードを見てみた。(確か最終更新日2002年度だったのでSSE3は使ってなさそうな気がする。)
http://homepage1.nifty.com/herumi/
にてダウンロードできるPentium4に最適化されたMT法乱数生成ルーチンの一部に
私にとっては珍しいコードがあった。


char *mallocPtr;
myMT_t *mt;
const int alignMask = 15; /* = 2^n - 1 */
int unit;

mallocPtr = (char *)malloc(sizeof(myMT_t) + alignMask);
if (mallocPtr == NULL) return NULL;

mt = (myMT_t *)( ( (int)mallocPtr + alignMask) & ~alignMask);
mt->mallocPtr = mallocPtr;

何故こんなことをやっているのだろう?
分かった!SSEは16byte単位でalignされていないといけないからこのような処理をしたと思った。
納得。こういうアプローチの仕方もあるのかと思った。


私は直接ポインタ値をずらし、ずらした先の ( -sizeof(void *) )のアドレスに真のポインタ値を保存というとってもデンジャーな方法を取っていました。ポインタ値を少しでも間違えて開放すると一気にバグるというすばらしいallocatorである。
確保したメモリ領域を二分木かなんかで保存して領域を開放したいとなったらポインタ値が多少ずれてても上手く開放できるようなものを作るのが一番だと感じた。(でも面倒・・・)
詳しくはgoogle:dkutil_cstd内に含まれているdkcstd_aligned_malloc()の実装を見てみてください。

*1:もっと速い方法のサイトを知っている方がいらっしゃいましたら是非連絡ください