ブックマーク / komorinfo.com (7)

  • C++17におけるコピー省略(Copy Elision)

    C++17では、この式の x はデフォルトコンストラクタにより直接初期化される。この式では、オブジェクトのコピーやムーブは一切発生しない。この挙動はC++標準規格で厳密に定義されており1、たとえ T がコピー/ムーブ不可能な型であっても、問題なくコンストラクトすることができる2。 // コピー構築やムーブ構築ができない型 class T { public: T() = default; T(const T&) = delete; T(T&&) = delete; T& operator=(const T&) = delete; T& operator=(T&&) = delete; }; int main() { T x = T(T(T())); // C++14ではエラー、C++17ではOK }

    C++17におけるコピー省略(Copy Elision)
    zu2
    zu2 2023/05/31
  • 安定性が向上した詰将棋エンジン『KomoringHeights v1.0.0』を公開した

    # v1.0.0における解答の様子 v0.5.0 の探索部は、大きく分けてMain SearchとPost Searchの2つに分かれていた。Main Searchは、与えられた局面が詰みかどうかを調べる探索である。一方、Post SearchはMain Searchで見つけた詰み局面のグラフ構造を再探索して双方最善を尽くしたときの詰み手順を構成する探索である。 探索部が2つに分かれていた理由は、Main Searchだけでは自然な詰み手順が構成できないからだった。Main Searchではdf-pnアルゴリズムと呼ばれる詰将棋と相性が良い探索を用いていた。df-pnアルゴリズムは詰みの判定自体は高速なのだが、見つけた手が必ずしも最善手と一致するとは限らない。最善手ではない手をベースに詰み手順を構成すると、人間から見て不自然な手順になってしまう。 そのため、Main Searchの後のP

    安定性が向上した詰将棋エンジン『KomoringHeights v1.0.0』を公開した
    zu2
    zu2 2023/01/08
  • C++でループをアンロールする

    #C++で重いループを高速化するときに、ループアンローリングしたくなることがしばしばある。ループアンロールによりバイナリサイズは肥大化してしまうが、条件分岐の削減やパイプラインストールの抑制によりそこそこの高速化が期待できる場合が多い。 C++で行儀よくループアンロールする方法は大きく分けて3つある。 Hand Unrolling: ループの中身を(マクロ関数などを用いて)展開するUnroller: メタ関数とラムダ式を用いてコードを展開するPragma: コンパイラに指示してアンロールしてもらうこれらはそれぞれメリット/デメリットがあるため状況に応じて使い分ける必要がある。それぞれ順に説明していく。 Hand Unrolling #include <iostream> // 式 p を 4 回連打するマクロ関数 #KOMORI_UNROLL_4(p) \ do { \ p; \ p; \

    C++でループをアンロールする
    zu2
    zu2 2022/12/21
  • コンパイル時に重複のある順列を扱う

    以下のコード例のように、整数型または列挙型の重複順列からそのインデックスを求めたり、逆にインデックスに対応する重複順列を生成することができる。 #include "komoperm/komoperm.hpp" enum Hoge { A, B, C, }; int main() { constexpr komoperm::Permutations<Hoge, A, A, A, B, B, C> p; static_assert(p.Size() == 60, "The number os possible permutations is 60"); static_assert(p.Index({B, A, B, C, A, A}) < 60, "{B, A, B, C, A, A} is a permutation of {A, A, A, B, B, C}"); static_asser

    コンパイル時に重複のある順列を扱う
    zu2
    zu2 2022/08/01
  • 型リストに対する展開回数を抑えたC++テンプレート

    ## ページの内容は C++14 を想定して書かれている。C++11 では一部使えない記法が含まれているため注意。 C++template meta programming(TMP)をするとき、展開深さ上限に達したり、メモリ不足によりエラーになったりすることがしばしばある。このような問題はあまり頻繁に遭遇することはないが、いざ遭遇すると普通の C++ とは異なる感覚が要求されるため頭を悩ませることが多い。 記事は、型リストに対する基的なテンプレートに絞って再帰深度を抑えるテクニックを説明する。具体的には、以下の4つのメタ関数を扱う。 型がリストに含まれるか(kIsAnyOf)型が何番目にあるか(kFind)条件を満たす型が何番目にあるか(kFindIf)N番目の型は何か(NthType)型リストから型やインデックスを取り出す関数たちである。これらは型リストに対するとても基的な機能

    型リストに対する展開回数を抑えたC++テンプレート
    zu2
    zu2 2022/06/17
  • 難解作品が解ける詰め将棋エンジン KomoringHeights v0.5.0 を公開した

    合流検出の実装はかなり複雑だ。詰将棋探索では探索中の局面を置換表(メモリ)に保存する必要があるのだが、合流検出のためにはこれを増やす必要がある。具体的には、v0.4.1 では 1 局面あたりの置換表エントリサイズは 32 byte であったのに対し、v0.5.0 では親局面のポインタ(12 byte)と合流フラグ(8 byte)を追加で持たせているため、サイズが 56 byte(1.5倍)に膨れ上がっている2。 さらに、合流検出のアルゴリズム自体もそれほど単純ではない。合流の可能性がある局面を見つけるたびに、再帰的に局面をさかのぼって合流検出のフラグを立てに行く必要がある。1回の計算量は大したことがないが、長時間探索する場合は無視できない計算量になりうる。 これらの理由から、合流検出を実装したことでNPS(単位時間あたりの探索局面数)がかなり低下する……はずだった。しかし、置換表のデータ構

    難解作品が解ける詰め将棋エンジン KomoringHeights v0.5.0 を公開した
    zu2
    zu2 2022/06/03
  • 詰将棋ソルバーにおけるGHI問題対策

    将棋ソルバーの開発で困ることが多いGHI問題について、正しい対策方法を調べたのでまとめる。ページは主に以下の文献紹介と詰将棋に対して適用する際の個人的な考察をまとめたものになっている。 [1] Kishimoto, Akihiro and Martin Müller. “A solution to the GHI problem for depth-first proof-number search.” Inf. Sci. 175 (2005): 296-314.GHI問題 #Graph History Interaction(GHI)問題とは、詰将棋のようなループを含むAND/OR木の探索で現れる問題である。 AND/OR木の探索では、局面の探索結果を一時的に保存する手段として置換表が多く用いられる。置換表に探索結果を保存することで、別経路で同一局面に合流した時に以前の探索結果を流用

    詰将棋ソルバーにおけるGHI問題対策
    zu2
    zu2 2021/12/08
  • 1