Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
ビットボードの実装を眺めていて、少し最適化を試してみました。
メインの変更は一つ目のコミットで、perft を試してみて Linux / CPU Zen2 / Compiler clang18 の環境で 7% くらい高速化しました。先手の香車の効きを求めるところで、1 を下位ビット側にビットシフト複数回で伝搬させる代わりに、MSB64 を使って最上位に立っている 1 の場所を求める実装としました。
こういう処理は本質的に x86 における bsr や lzcnt 命令を使うか、ビットシフトを log(bitwidth) 回行う必要があるはずです。Zen4 より前では では bsr のコストが高いという理由からか、lzcnt 命令にコンパイルされるようでした。命令数としては bsr の方が得にはなるのでコンパイラオプションとして
-mno-lzcnt
つけるとか、処理をいじって lzcnt 向けに最適化するとかやってみたのですが、速くなる感じはなかったので、コードのシンプルさなども考えて今の比較的わかりやすい書き方にしました。AgnerFog https://www.agner.org/optimize/instruction_tables.pdf を見る限り AMD 系だと lzcnt のレイテンシが 1 で、Intel 系だと 3 のようなので、Intel 系では僅かにしか速くなっていないとは思います。
具体的には
と
の比較ということになりますが、前者のレイテンシは 7 cycles で、後者のレイテンシは Intel だと lzcnt で 6 cycles、bsr で 5 cycles となります。
また、128bit のデクリメントの最適化もやってみました。さらに unpack をなくしてみるのも試したのですが、やっぱり unpack した状態でデクリメントする現状の実装のほうが速そうなので諦めました。