サブロウ丸

Sabrou-mal サブロウ丸

主にプログラミングと数学

master mind by c++; part11 namespace

今回やること

namespaceの導入

背景

$ valgrind --tool=callgrind --callgrind-out-file=./callgrind.out ./bin/mastermind 4 4 --test
$ gprof2dot -f callgrind ./callgrind.out | dot -Tpdf -o report.pdf

でプロファイルをしたところ,

f:id:inarizuuuushi:20210619091841p:plain:w200

countHitBlow関数が全体の35.57%を占めていることが分かりました.

f:id:inarizuuuushi:20210619092204p:plain:w200

その中でもvectorの生成が時間を要しているようですね.

/**
* @fn HitBlow countHitBlow(Code &code, Code &guess)
* @brief コード2つから, hit, blowを計算する
* @param[in] code コード
* @param[in] guess コード
* @param[in] config パラメタ
* @return (hit, blow)
*/
auto countHitBlow(
      Code &code,
      Code &guess,
      Config &config
      )
{
    std::vector<int> x(config.nColors, 0);  // ここか
    std::vector<int> y(config.nColors, 0);  // ここか
    int hit = 0, blow = 0;
    ... ( 中略 ) ...
    return HitBlow(hit, blow);
}

メモリの動的確保は時間がかかるので, メモリの動的確保をなるべく減らすべく次のように変更してみます.

std::vector<int> x(1, 0);  // 外に出してみた
std::vector<int> y(1, 0); // 外に出してみた
/**
* @fn HitBlow countHitBlow(Code &code, Code &guess)
* @brief コード2つから, hit, blowを計算する
* @param[in] code コード
* @param[in] guess コード
* @param[in] config パラメタ
* @return (hit, blow)
*/
auto countHitBlow(
      Code &code,
      Code &guess,
      Config &config
      )
{
   if ( x.size() < config.nColors )
   {
      x.resize(config.nColors);  // 必要な分だけresize
      y.resize(config.nColors);  // 必要な分だけresize
   }
   std::fill(x.begin(), x.end(), 0);  // reset
   std::fill(y.begin(), y.end(), 0);  // reset
   int hit = 0, blow = 0;
   ... ( 中略 ) ...
   return HitBlow(hit, blow);
}

これでもコンパイルは通りますが, x, y変数がglobal変数となってしまいます. そのため他の変数空間を汚さないために, 自作のコード部分を新しくnamespaceで囲います. これにより, 変数x, yは自分のnamespace内のグローバル変数として定義されることになり, 他のライブラリに影響を与えませんし、他のライブラリから意図的にアクセスされない限り参照されることもありません。

namespaceは下記のように囲みます. 入れ子にすることも可能です.

namespace 名前{

a func(int x, int y){ ... };

};

コード差分

実験

10回の実行時間の平均で比較します.

nColors nPins totalTime [msec] new countHitBlow - totalTime [msec]
5 5 3.7 0.1
6 5 679.7 41.5
7 5 18467.3 16983.7

速くなっていますね.

まとめ

namespaceを導入し, 安全にグローバル変数を用意してvectorの動的生成の回数を減らすことで実行時間を減少させることができました

コード

他の記事