ulong flip(int pos, ulong P, ulong O) { ulong4 flipped, OM, outflank, mask; OM.x = O; OM.yzw = O & 0x7e7e7e7e7e7e7e7eUL; mask = (ulong4) (0x0080808080808080UL, 0x7f00000000000000UL, 0x0102040810204000UL, 0x0040201008040201UL) >> (63 - pos); outflank = (0x8000000000000000UL >> clz(~OM & mask)) & P; flipped = (-outflank * 2) & mask; mask = (ulong4) (0x0101010101010100UL, 0x00000000000000feUL, 0x0002040810204080UL, 0x8040201008040200UL) << pos; outflank = mask & ((OM | ~mask) + 1) & P; flipped |= (outflank - (outflank != 0)) & mask; return flipped.x | flipped.y | flipped.z | flipped.w; }これを試しにGPGPUに実装してみました。 GPUでは同期して動作するある程度のスレッド数(CUDAでは32)が必要なので、5カ所空きの完全読みを並列処理するようにしました(5! = 120通りのBrute force)。
SIMTが有効に使えるとき、GPUはCPU以上の演算能力がありますが、Brute forceのために打てない空きや、α-βでは枝刈りされるノードにまで演算ユニットを割り当てることになり、(CPUとGPUの性能にもよりますが)残念ながらピーク性能としてもCPUのα-βより1桁遅い結果になりました。
これでもうまく使えば高速化できる可能性は残りますが、GPUの構成上ある程度のブロックをまとめて渡さなければピーク性能は得られず、実装は容易ではありません。
というわけで実用性に欠けるコードになりましたが、同じことを考えている方のために、参考までに公開します。(GPL3)
warp内のsyncthreadsを省略できるのと(ifの中なので特に重要)、voteやshuffleが使えると性能上有利なので、CUDAにより実装しています。