Skip to content

高速化(C++)

  • 基本的に、本質的な改善に時間を使うほうがよくて、定数倍高速化などは最後の最後に行うほうが良い
    • 高速化が本質じゃないならば

SIMD

AoS/SoA

  • Array of Structure(AoS)、Structure of Arrays(SoA)
  • キャッシュ効率やSIMDなどの最適のされやすさなど

キャッシュブロッキング

Cache-Oblivious

Branchless/Eytzinger layout

細かいテク

bit演算、bitset高速化、bitboard

SIMD化されやすい書き方、キャッシュに乗りやすい書き方

vectorの途中の要素をO(1)で消すテク

  • 消したいv[i]を末尾の要素とswapし、pop_back()する

[0,N)の整数の集合を管理する定数倍が軽いデータ構造(IndexSet)

計算量オーダーより計算回数

  • ヒューリスティック系だと、Nが大きくなかったりするため、計算量オーダー的にはO(N)でもO(logN)より高速に動作する場合がある
  • 連結成分を見つけるのにUnionFind(dsu)を使うより、単純にBFSで列挙した方が実行時間が速かったりする

キャッシュミスを減らす

動的メモリ確保を減らす

メモリ周り

  • 要素数が少ないvectorを大量に確保する場合など、確保に時間が掛かる可能性がある
    • vectorではなく配列で確保、使い回す、1次元で確保、など
  • 大量にメモリを確保する場合、メモリ解放にも時間が掛かる可能性がある
    • 行儀が悪いが、exit(0)quick_exit(0)で後処理を省略して終わらせる
      • exitはglobal変数やスレッド変数などの後処理やファイルストリームのフラッシュは実行される
      • quick_exitはそれらを行わない。が、環境によっては使えないかも
  • グラフの隣接リストをCSRで持つ

malloc/allocator置き換え、custom allocator

pmr::monotonic_buffer_resource mbr;
pmr::vector<int> v(&mbr);

STL周り

逆操作で戻す

  • 同じ処理を2回 or 変化したやつだけ保持しておいてそれだけ戻す or undo操作で初期状態に戻す
    • Nが大きいのに変化する要素が少ない場合に有効
  • DFS的にノードを辿ったりする場合は、ノードごとに独立に状態を作るのではなく、undo操作&advance操作でノード間を移動するようにすると状態のコピーがなくなる

分岐を減らす

入力に合わせて使う型を切り替える

高速な実装