最新

Miyako Shogi System

コツコツ改良、へこたれない
2014| 1|
2013| 12|
2012| 01| 02| 04| 05| 06| 07| 08| 09| 10|
2011| 01| 02| 03| 04| 05| 07| 08| 10| 11| 12|
2010| 02| 03| 06| 07| 08| 09| 10| 12|

2012/10/14

SSEによるbitboardの実装の検討

bitboardによる先手銀の駒を取らない移動手のコードは、

org=p->bitboard[BLACK][P_GIN];                  // 銀
while ( (from=bit_pop1st(&org)) >= 0 ) {
  and128(t,attack_gin_b[from],target);
  mt=from+(P_GIN<<14);
  while ( (to=bit_pop1st(&t)) >= 0 ) {
    pin_check()
    *p_move++=mt+(to<<7);
    if ( (to <= 26) || (from <= 26) ) *p_move++=mt+(to<<7)+PROMOTE_BIT;
  }
}

bit_pop1stはbitboardのLSBから立っているビット位置を返し、そのビットをクリアする関数である。bitboardが全てゼロのときは-1を返すようにした。

static inline int
bit_pop1st(BITBOARD *x)
{
int pos=-1;
#ifdef  __x86_64__
  if ( x->l64 ) {
    pos=__builtin_ctzll(x->l64);
    x->l64&=(x->l64-1); // reset bit
  }
  else if ( x->h64 ) {
    pos=__builtin_ctzll(x->h64)+64;
    x->h64&=(x->h64-1); // reset bit
  }
#else
  if ( x->l ) {
    pos=__builtin_ctz(x->l);
    x->l&=(x->l-1);     // reset bit
  }
  else if ( x->m ) {
    pos=__builtin_ctz(x->m)+32;
    x->m&=(x->m-1);     // reset bit
  }
  else if ( x->h ) {
    pos=__builtin_ctz(x->h)+64;
    x->h&=(x->h-1);     // reset bit
  }
#endif
  return pos;
}

SSE2ではand128などの128bit論理演算が可能である。

#define zero128(r)       (r).x=_mm_xor_si128((r).x,(r).x)
#define and128(r,a,b)    (r).x=_mm_and_si128((a).x,(b).x)
#define or128(r,a,b)     (r).x=_mm_or_si128((a).x,(b).x)
#define xor128(r,a,b)    (r).x=_mm_xor_si128((a).x,(b).x)
#define andnot128(r,a,b) (r).x=_mm_andnot_si128((b).x,(a).x)
#define andor128(r,a,b)  (r).x=_mm_or_si128((r).x,_mm_and_si128((a).x,(b).x))

SSE4では次の比較関数も使える。Zフラグに結果が入る。

#define test128(a)       (!_mm_testz_si128((a).x,(a).x))
#define andtest128(a,b)  (!_mm_testz_si128((a).x,(b).x))

上記手生成コードでSIMD命令が有効となるのはand128であろう。後の命令は非SIMD命令であり、SIMDレジスタと通常レジスタの移動のオーバーヘッドがあるだろう。

リンクはご自由に (Miyako Shogi System Kyoto Japan)

ダウンロードのページ

Lighttpd

DreamPlug