第14章 ベンチマークおよび調整

14.1. 最適な Solver 設定を見つける

Planner は、複数の最適化アルゴリズムに対応しているため、おそらく、どのアルゴリズムが最適なのか疑問に思うはずです。一般的に、他のと比べて良い結果を得られる最適化アルゴリズムを選択することはできますが、良い結果を得られるかどうかは問題のドメインに大きく依存します。多くの Solver フェーズには、調整可能なパラメーターが含まれます。ほとんどの場合、設定せずに使用してもかなり良い結果は得られますが、パラメーターを使用することで結果が大きく変わります。

このため、Planner にはベンチマーカーが用意されています。これを使用して、開発過程で、異なる Solver フェーズに異なる設定を試すことができるため、本番環境での計画問題に最適な設定を使用できます。

benchmarkOverview

14.2. ベンチマーク設定

14.2.1. optaplanner-benchmark に依存関係を追加

このベンチマーカーは、optaplanner-benchmark という名前の別のアーティファクトにあります。

Maven を使用する場合は、pom.xml ファイルに依存関係を追加します。

    <dependency>
      <groupId>org.optaplanner</groupId>
      <artifactId>optaplanner-benchmark</artifactId>
    </dependency>

これは、Gradle、Ivy、および Buildr と同じです。このバージョンは、使用される optaplanner-core バージョンと完全に同じです (optaplanner-bom をインポートする場合は自動的にこのようになります)。

Ant を使用している場合は、おそらく、ダウンロードした Zip の binaries ディレクトリーから、必要な JAR をコピーしています。

14.2.2. PlannerBenchmark の構築と実行

PlannerBenchmarkFactory で、PlannerBenchmark インスタンスを構築します。クラスパスリソースとして提供されている、XML のベンチマーク設定ファイルを使用して設定します。

        PlannerBenchmarkFactory plannerBenchmarkFactory = PlannerBenchmarkFactory.createFromXmlResource(
                "org/optaplanner/examples/nqueens/benchmark/nqueensBenchmarkConfig.xml");
        PlannerBenchmark plannerBenchmark = plannerBenchmarkFactory.buildPlannerBenchmark();
        plannerBenchmark.benchmark();

ベンチマーク設定は、以下のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<plannerBenchmark>
  <benchmarkDirectory>local/data/nqueens</benchmarkDirectory>

  <inheritedSolverBenchmark>
    <problemBenchmarks>
      ...
      <inputSolutionFile>data/nqueens/unsolved/32queens.xml</inputSolutionFile>
      <inputSolutionFile>data/nqueens/unsolved/64queens.xml</inputSolutionFile>
    </problemBenchmarks>
    <solver>
      ...<!-- Common solver configuration -->
    </solver>
  </inheritedSolverBenchmark>

  <solverBenchmark>
    <name>Tabu Search</name>
    <solver>
      ...<!-- Tabu Search specific solver configuration -->
    </solver>
  </solverBenchmark>
  <solverBenchmark>
    <name>Simulated Annealing</name>
    <solver>
      ...<!-- Simulated Annealing specific solver configuration -->
    </solver>
  </solverBenchmark>
  <solverBenchmark>
    <name>Late Acceptance</name>
    <solver>
      ...<!-- Late Acceptance specific solver configuration -->
    </solver>
  </solverBenchmark>
</plannerBenchmark>

この PlannerBenchmark は、2 つのデータセット (32queens および 64queens) を使用して、3 つの設定 (タブー探索、焼きなまし法、およびレイトアクセプタンス) を試すため、Solver を全部で 6 回実行します。

すべての <solverBenchmark> 要素には、Solver 設定と、1 つ以上の <inputSolutionFile> 要素があります。未解決の解の各ファイルで、Solver 設定を実行します。name 要素はオプションです (ない場合は生成されます)。inputSolutionFile は、SolutionFileIO (ワーキングディレクトリーへの相対バス) から読み込まれます。

注記

(たとえば <inputSolutionFile> 要素で) フォワードスラッシュ (/) をファイルセパレーターとして使用します。これは、(Windows を含む) どのプラットフォームでも有効です。

ファイルセパレーターにバックスラッシュ (\) は使用しないでください。Linux と Mac では機能しないため、移植性がなくなります。

ベンチマークレポートは、<benchmarkDirectory> 要素 (ワーキングディレクトリーへの相対バス) で指定したディレクトリーに記述されます。

注記

benchmarkDirectory は、ソース制御の範囲外で、ビルドシステムで削除されないディレクトリーにすることが推奨されます。この方法を使用すれば、生成したファイルによってソース制御が大きくなることはなく、クリーンビルドを行っても失われることがありません。通常、このディレクトリーは ローカル と呼ばれます。

Exception または Error が 1 つのベンチマークで発生したとき、(Planner のその他の機能とは異なり) ベンチマーカー全体でフェイルファーストにはなりません。代わりに、ベンチマーカーは、その他のすべてのベンチマークを実行し続け、ベンチマークレポートを作成してからフェイルします (ベンチマークが 1 つでも失敗した場合)。失敗したベンチマークは、ベンチマークレポートに記録されます。

14.2.2.1. 継承される Solver ベンチマーク

詳細のレベルを下げるために、複数の <solverBenchmark> 要素で共通している部分が <inheritedSolverBenchmark> 要素に抽出されます。すべてのプロパティーは <solverBenchmark> 要素で上書きすることができますが、<constructionHeuristic><localSearch> などの継承された Solver フェーズは上書きされず、Solver フェーズリストの最後に追加されます。

14.2.3. SolutionFileIO: ソリューションファイルの入出力

14.2.3.1. SolutionFileIO インターフェース

ベンチマーカーは、ソリューション をロードするために、入力ファイルを読み込めるようにする必要があります。また、各ベンチマークで最適な ソリューション を出力ファイルに書き込むことも必要になるかもしれません。その場合は、SolutionFileIO インターフェースを実装するクラスを使用します。

public interface SolutionFileIO {

    String getInputFileExtension();

    String getOutputFileExtension();

    Solution read(File inputSolutionFile);

    void write(Solution solution, File outputSolutionFile);

}

SolutionFileIO インターフェースは optaplanner-persistence-common JAR (optaplanner-benchmark JAR の依存関係) にあります。

14.2.3.2. XStreamSolutionFileIO: デフォルトの SolutionFileIO

デフォルトでは、ベンチマーカーは XStreamSolutionFileIO インスタンスを使用して、ソリューションの読み書きを行います。

XStream アノテーションでアノテートした Solution クラスについて、ベンチマーカーに指定する必要があります。

    <problemBenchmarks>
      <xStreamAnnotatedClass>org.optaplanner.examples.nqueens.domain.NQueens</xStreamAnnotatedClass>
      <inputSolutionFile>data/nqueens/unsolved/32queens.xml</inputSolutionFile>
      ...
    </problemBenchmarks>

XStreamSolutionFileIO は、カスタマイズした XStream インスタンスを使用するため、このような入力ファイルでは、XStream インスタンスではなく、XStreamSolutionFileIO インスタンスで指定します。

警告

XStream (および一般的には XML ) は、非常に詳細な書式を使用しています。このフォーマットに非常に長いデータセットを読み込んだり書き込んだりすると、OutOfMemoryError が発生したり、パフォーマンスが低下する原因になります。

14.2.3.3. カスタムの SolutionFileIO

その他に、カスタマイズした SolutionFileIO 実装を作成し、solutionFileIOClass 要素で設定します。

    <problemBenchmarks>
      <solutionFileIOClass>org.optaplanner.examples.machinereassignment.persistence.MachineReassignmentFileIO</solutionFileIOClass>
      <inputSolutionFile>data/machinereassignment/import/model_a1_1.txt</inputSolutionFile>
      ...
    </problemBenchmarks>

出力ファイルを入力ファイルとして読み込むことが推奨されます。これは、getInputFileExtension()getOutputFileExtension() が同じ値を返すことを意味します。

警告

SolutionFileIO 実装はスレッドセーフである必要があります。

14.2.3.4. データベース (またはその他のリポジトリー) からの入力ソリューションの読み込み

ベンチマーク設定は、現在データセット毎に <inputSolutionFile> 要素を指定する必要があります。データセットが、データベースまたは別のタイプのリポジトリ-にある場合にこの問題に対処する方法は 2 つあります。

  • データベースからデータセットを抽出し、(たとえば XStreamSolutionFileIO を使用した XML として) ローカルファイルにシリアル化します。次に、そのファイルを <inputSolutionFile> 要素として使用します。
  • 各データセットに対して、データセットの固有の ID を保持するテキストファイルを作成します。その識別子を読み込み、その ID でデータベースに接続し、問題を抽出する カスタムの SolutionFileIO を記述します。そのテキストファイルは <inputSolutionFile> 要素として設定します。
注記

ローカルファイルの方が常に速く、ネットワーク接続も必須ではありません。

14.2.4. HotSpot コンパイラーのウォーミングアップ

HotSpot JIT コンパイル (そして、おそらく DRL コンパイルでも) CPU 時間がなくなるため、ウォーミングアップが終わっていない、最初 (もしくは最初の数回) のベンチマークは信頼できません。

このようなねじれを避けるために、ベンチマーカーでは、実際のベンチマークを実行する前に、複数のベンチマークを一定期間実行できます。通常、ウォーミングアップは 30 秒行えば十分となります。

<plannerBenchmark>
  ...
  <warmUpSecondsSpentLimit>30</warmUpSecondsSpentLimit>
  ...
</plannerBenchmark>
注記

このウォーミングアップに費やした時間は、データセットのロードにかかった時間には含まれません。データセットが大きくなると、設定に指定した時間よりもはるかに長い間、ウォーミングアップの実行にかかるためです。

14.2.5. ベンチマークの詳細: 事前定義済み設定

一般的な Solver 設定に対するベンチマークを短時間で設定する場合は、solverBenchmarks ではなく solverBenchmarkBluePrint を使用します。

<?xml version="1.0" encoding="UTF-8"?>
<plannerBenchmark>
  <benchmarkDirectory>local/data/nqueens</benchmarkDirectory>
  <warmUpSecondsSpentLimit>30</warmUpSecondsSpentLimit>

  <inheritedSolverBenchmark>
    <problemBenchmarks>
      <xStreamAnnotatedClass>org.optaplanner.examples.nqueens.domain.NQueens</xStreamAnnotatedClass>
      <inputSolutionFile>data/nqueens/unsolved/32queens.xml</inputSolutionFile>
      <inputSolutionFile>data/nqueens/unsolved/64queens.xml</inputSolutionFile>
      <problemStatisticType>BEST_SCORE</problemStatisticType>
    </problemBenchmarks>
    <solver>
      <scanAnnotatedClasses/>
      <scoreDirectorFactory>
        <scoreDefinitionType>SIMPLE</scoreDefinitionType>
        <scoreDrl>org/optaplanner/examples/nqueens/solver/nQueensScoreRules.drl</scoreDrl>
        <initializingScoreTrend>ONLY_DOWN</initializingScoreTrend>
      </scoreDirectorFactory>
      <termination>
        <minutesSpentLimit>1</minutesSpentLimit>
      </termination>
    </solver>
  </inheritedSolverBenchmark>

  <solverBenchmarkBluePrint>
    <solverBenchmarkBluePrintType>EVERY_CONSTRUCTION_HEURISTIC_TYPE_WITH_EVERY_LOCAL_SEARCH_TYPE</solverBenchmarkBluePrintType>
  </solverBenchmarkBluePrint>
</plannerBenchmark>

次の SolverBenchmarkBluePrintTypes に対応します。

  • EVERY_CONSTRUCTION_HEURISTIC_TYPE: すべてのタイプの構築ヒューリスティック (FF、FFD、CI など) を実行します。
  • EVERY_LOCAL_SEARCH_TYPE: デフォルトの構築ヒューリスティックを使用して、すべての局所選択タイプ (タブー選択、レイトアクセプランスなど​) を実行します。
  • EVERY_CONSTRUCTION_HEURISTIC_TYPE_WITH_EVERY_LOCAL_SEARCH_TYPE: すべての局所探索タイプで、すべての構築ヒューリスティックタイプを実行します。

14.2.6. ベンチマークを実行した出力ソリューションの記述

各ベンチマークを実行したときの最適解を benchmarkDirectory に記述できます。このファイルが使われることはほぼなく、サイズが肥大化すると考えられるので、これはデフォルトでは無効になっています。また、データセットが大きい時に 1 回のベンチマークでの最適解を記述すると、特に XStream XML などの詳細なフォーマットでは、時間とメモリーを大きく消費 (し OutOfMemoryError が発生) する可能性があります。

benchmarkDirectory でこのような解 (ソリューション) を記述するには、writeOutputSolutionEnabled を有効にします。

    <problemBenchmarks>
      ...
      <writeOutputSolutionEnabled>true</writeOutputSolutionEnabled>
      ...
    </problemBenchmarks>

14.2.7. ベンチマークのログ

ベンチマークのログは、Solver ログ と同じように設定します。

ログメッセージを、ベンチマークごとに異なるファイルに分けるには、ShiftingAppender の MDCsingleBenchmark.name キーを使用します。たとえば、 Logback の場合は logback.xml に以下のように設定します。

  <appender name="fileAppender" class="ch.qos.logback.classic.sift.SiftingAppender">
    <discriminator>
      <key>singleBenchmark.name</key>
      <defaultValue>app</defaultValue>
    </discriminator>
    <sift>
      <appender name="fileAppender.${singleBenchmark.name}" class="...FileAppender">
        <file>local/log/optaplannerBenchmark-${singleBenchmark.name}.log</file>
        ...
      </appender>
    </sift>
  </appender>

14.3. ベンチマークレポート

14.3.1. HTML レポート

ベンチマークを実行すると、benchmarkDirectoryindex.html という名前で HTML レポートが作成されます。このファイルをブラウザーで開きます。このファイルには、以下の内容を含むベンチマークの概要が記述されます。

  • サマリー統計: グラフおよび表
  • inputSolutionFile に関する問題の統計データ: グラフおよび CSV
  • 各 Solver 設定 (ランク付け): コピーアンドペーストに便利
  • ベンチマーク情報: 設定、ハードウェアなど
注記

グラフ生成には、優れた JFreeChart ライブラリーが使用されます。

HTML レポートの数値の書式には、デフォルトロケールが適用されます。作成したベンチマークレポートを他国の人と共有する場合は、locale を上書きすることも検討してください。

<plannerBenchmark>
  ...
  <benchmarkReport>
    <locale>en_US</locale>
  </benchmarkReport>
  ...
</plannerBenchmark>

14.3.2. Solver のランク付け

ベンチマークレポートでは、自動的に Solver にランクが付けられます。ランク 0Solver は、お気に入りの Solver と呼ばれます。総合的には最良のパフォーマンスですが、すべての問題で最良とは限りません。本番環境では、このお気に入りの Solver を使用することが推奨されます。

Solver のランク付け方法は複数あり、以下のように設定します。

<plannerBenchmark>
  ...
  <benchmarkReport>
    <solverRankingType>TOTAL_SCORE</solverRankingType>
  </benchmarkReport>
  ...
</plannerBenchmark>

以下の solverRankingTypes に対応しています。

  • TOTAL_SCORE (デフォルト): 全体のスコアを最大にし、すべてのソリューションを実行した場合のコスト全体を最小限に抑えます。
  • WORST_SCORE: 最悪のシナリオを最小限に抑えます。
  • TOTAL_RANKING: 全体のランク付けを最大にします。これを使用すると、データセットのサイズまたは難易度が大きく異なる場合に、Score の差異を大きくします。

Solvers に失敗したベンチマークが 1 つでもあれば、ランク付けされません。完全に初期化されていないソリューションがある Solvers のランクは低くなります。

Comparator を実装すれば、カスタムのランクも使用できます。

  <benchmarkReport>
    <solverRankingComparatorClass>...TotalScoreSolverRankingComparator</solverRankingComparatorClass>
  </benchmarkReport>

もしくは、SolverRankingWeightFactory を実装します。

  <benchmarkReport>
    <solverRankingWeightFactoryClass>...TotalRankSolverRankingWeightFactory</solverRankingWeightFactoryClass>
  </benchmarkReport>

14.4. 要約統計

14.4.1. 最高スコアの要約 (グラフおよび表)

各 Solver の inputSolutionFile に対する最高スコアを表示します。

最適な Solver 設定を可視化するのに便利です。

図14.1 最高スコアの要約統計

bestScoreSummary

14.4.2. 最高スコアのスケーラビリティー要約 (グラフ)

各 Solver 設定の問題スケールあたりの最高スコアを表示します。

各 Solver 設定のスケーラビリティーを可視化するのに便利です。

注記

@ValueRangeProvider メソッドのシグネチャーが、(CountableValueRange または Collection ではなく) ValueRange を返すと、問題のスケールが 0 を報告します。相違点については ValueRangeFactory を参照してください。

14.4.3. 最高スコア分布の要約 (グラフ)

各 Solver 設定の inputSolutionFile に従って、最高スコアを表示します。

各 Solver 設定の信頼性を可視化するのに役に立ちます。

図14.2 最高スコア分布の要約統計

bestScoreDistributionSummary

この要約を使用するには、統計ベンチマーク を有効にします。

14.4.4. 勝利スコアの差の要約 (グラフおよび表)

各 Solver 設定の inputSolutionFile に従って、勝利スコアの差を表示します。勝利スコアの差は、その特定の inputSolutionFile と勝利 Solver 設定のスコアを比較したスコアの差となります。

最高スコア要約の結果を拡大するのに役に立ちます。

14.4.5. 最低スコアの差の割合 (ROI) の要約 (グラフおよび表)

各 Solver 設定の inputSolutionFile に従って、投資効果率 (ROI) を表示します (この特定の inputSolutionFile に対する最低の Solver 設定からアップグレードする場合)。

意思決定者への投資対効果を可視化するのに便利です。

14.4.6. 平均計算数の要約 (グラフおよび表)

スコア計算の速度 (各 Solver 設定に対する問題スケールあたりの平均計算数) を表示します。

異なるスコア計算プログラムや、スコアルール実装を比較するのに便利です (Solver 設定は同じであることが前提です)。また、追加の制約を行った場合のスケーラビリティーのコストを測定するのにも役に立ちます。

14.4.7. 経過時間の要約 (グラフおよび表)

各 Solver 設定の inputSolutionFile に従って、経過時間を表示します。固定時間制限に対してベンチマークを設定している場合、これは有益ではありません。

構築ヒューリスティックのパフォーマンスを可視化するのに便利です (その他の Solver フェーズが設定されていないことを前提としています)。

14.4.8. スケーラビリティーにかかった時間の要約 (グラフ)

各 Solver 設定の問題スケールにかかった時間を表示します。固定時間制限に対してベンチマークを行っている場合、これは有益ではありません。

構築ヒューリスティックのスケーラビリティーを推定するのに便利です (その他の Solver フェーズが設定されていないことを前提としています)。

14.4.9. 経過時間ごとの最高スコアの要約 (グラフ)

各 Solver 設定における経過時間ごとの最高スコアを表示します。固定時間制限に対してベンチマークを行っている場合、これは有益ではありません。

構築ヒューリスティックで、最高スコアと経過時間のトレードオフを可視化するのに便利です (その他の Solver フェーズが設定されていないことを前提としています)。

14.5. データセットに関する統計 (グラフおよび CSV)

14.5.1. 問題の統計の有効化

ベンチマーカーは、問題の統計をグラフおよび CSV (コンマ区切り値) ファイルとして benchmarkDirectory に出力するのをサポートします。これを設定するには、problemStatisticType 行を追加します。

<plannerBenchmark>
  <benchmarkDirectory>local/data/nqueens/solved</benchmarkDirectory>
  <inheritedSolverBenchmark>
    <problemBenchmarks>
      ...
      <problemStatisticType>BEST_SCORE</problemStatisticType>
      <problemStatisticType>CALCULATE_COUNT_PER_SECOND</problemStatisticType>
    </problemBenchmarks>
    ...
  </inheritedSolverBenchmark>
  ...
</plannerBenchmark>

複数の problemStatisticType 要素が許可されます。

注記

データセットごとの統計は、Solver の速度を著しく落とし、ベンチマークの結果に影響する可能性があります。したがって、この設定は任意で、デフォルトでは有効ではありません。

必須の要約統計が、Solver の速度を著しく落とすことはありません。

以下のタイプがサポートされます。

14.5.2. 経時最高スコア統計 (グラフおよび CSV)

時間の経過とともに最高スコアがどのように進化していったかを確認するには、以下を追加します。

    <problemBenchmarks>
      ...
      <problemStatisticType>BEST_SCORE</problemStatisticType>
    </problemBenchmarks>

図14.3 経時最高スコア統計

bestScoreStatistic
注記

(焼きなまし法などの) 時間勾配ベースのアルゴリズムは、実行する時間制限設定を変更すると、統計が変わります。これは、この焼きなましの実装が、経過した時間に基づいて自動的に速度を決定するためです。一方、タブー探索およびレイトアクセプタンスについては、自動的に変更することはありません。

経時最高スコア統計は、Solver が局所最適条件で一時的に身動きできなくなる スコアトラップ などの潜在的な異常を検出するのに非常に役に立ちます。

letTheBestScoreStatisticGuideYou

14.5.3. 経時ステップスコア統計 (グラフおよび CSV)

時間の経過とともにステップスコアがどのように進化していったかを確認するには、以下を追加します。

    <problemBenchmarks>
      ...
      <problemStatisticType>STEP_SCORE</problemStatisticType>
    </problemBenchmarks>

図14.4 経時ステップスコア統計

stepScoreStatistic

ステップスコア統計と、最高スコア統計を比較します (特に最高スコアが水平になる部分)。それが局所最適条件に到達した場合、Solver は、悪化したステップを選択して回避する必要があります。ただし、あまり悪化させることはできません。

警告

ステップスコア統計では、特に (焼きなまし法およびレイトアクセプタンスなどの) ステップが速いアルゴリズムにおいて、GC ストレスが原因で Solver が著しく遅くなっているのが確認できます。

14.5.4. 秒あたりカウントの計算統計 (グラフおよび CSV)

スコアが計算される速度を確認するには、以下を追加します。

    <problemBenchmarks>
      ...
      <problemStatisticType>CALCULATE_COUNT_PER_SECOND</problemStatisticType>
    </problemBenchmarks>

図14.5 秒あたりカウントの計算統計

calculateCountPerSecondStatistic
注記

ソリューションの初期化時に初期計算のカウントが高くなるのは一般的です。ごく一部のプランニングエンティティーだけを初期化している時点でのソリューションのスコア計算は、すべてのプランニングエンティティーを初期化したときよりはるかに簡単になります。

初期化を数秒間行ったあと、時折発生するストップザワールドのガベージコレクションの分裂を除き、計算カウントは比較的安定します。

14.5.5. 経時最適解変化統計 (グラフおよび CSV)

新しい最適解が 1 つ前の最適解 とどのぐらい異なるかを確認するには、以下を追加します。ここでは、値が異なるプランニング変数の数を数えていますが、複数回変更して最後には同じ値になった変数は除外されます。

    <problemBenchmarks>
      ...
      <problemStatisticType>BEST_SOLUTION_MUTATION</problemStatisticType>
    </problemBenchmarks>

図14.6 経時最適解変化統計

bestSolutionMutationStatistic

(人間のように振舞うアルゴリズムである) タブー探索を使用して、人間が、1 つ前の最適解を改善して新しい最適解にするのがどのぐらい難しいか判断します。

14.5.6. ステップあたりの Move 数 (グラフおよび CSV)

各ステップで選択して許可した Move 数が、時間の経過とともにどのように進化していったかを確認するには、以下を追加します。

    <problemBenchmarks>
      ...
      <problemStatisticType>MOVE_COUNT_PER_STEP</problemStatisticType>
    </problemBenchmarks>

図14.7 ステップ値の Move 数

moveCountPerStepStatistic
警告

この統計では、特に (焼きなまし法、レイトアクセプタンスなどの) ステップの速いアルゴリズムにおいて、GC ストレスが原因で Solver が著しく遅くなっているのが確認できます。

14.5.7. メモリー使用統計 (グラフおよび CSV)

メモリーの使用量を確認するには、以下を追加します。

    <problemBenchmarks>
      ...
      <problemStatisticType>MEMORY_USE</problemStatisticType>
    </problemBenchmarks>

図14.8 メモリー使用統計

memoryUseStatistic
警告

メモリー使用統計は、Solver に大きく影響することが確認されています。

14.6. ベンチマークに関する統計 (グラフおよび CSV)

14.6.1. 単一統計を有効にする

単一統計は、1 つの Solver 設定に対する 1 つのデータセットに関する統計です。問題の統計とは異なり、Solver 設定から集計しません。

ベンチマーカーは、1 つ統計を グラフおよび CSV (コンマ区切り値) ファイルとして benchmarkDirectory に出力するのをサポートします。設定する場合は singleStatisticType 行を追加します。

<plannerBenchmark>
  <benchmarkDirectory>local/data/nqueens/solved</benchmarkDirectory>
  <inheritedSolverBenchmark>
    <problemBenchmarks>
      ...
      <problemStatisticType>...</problemStatisticType>
      <singleStatisticType>PICKED_MOVE_TYPE_BEST_SCORE_DIFF</singleStatisticType>
    </problemBenchmarks>
    ...
  </inheritedSolverBenchmark>
  ...
</plannerBenchmark>

複数の singleStatisticType 要素が許可されます。

注記

ベンチマークあたりの統計は、Solver の速度を著しく落とし、ベンチマークの結果に影響する可能性があります。したがって、この設定は任意で、デフォルトでは有効ではありません。

以下のタイプがサポートされます。

14.6.2. 経時最高スコアの合計に一致する制約統計 (グラフおよび CSV)

どの制約が経時最高スコアに (どのぐらい) 一致するかを確認するには、以下を追加します。

    <problemBenchmarks>
      ...
      <singleStatisticType>CONSTRAINT_MATCH_TOTAL_BEST_SCORE</singleStatisticType>
    </problemBenchmarks>

図14.9 経時最高スコアの合計に一致する制約統計

constraintMatchTotalBestScoreStatistic

スコア計算が、制約の一致 をサポートする必要があります。Drools スコア計算 では、制約の一致が自動的にサポートされますが、Java インクリメント演算子によるスコア計算 ではさらなる作業が必要です。

警告

制約一致の合計統計は、Solver に大きく影響することが確認されています。

14.6.3. 経時ステップスコア合計に一致する制約統計 (グラフおよび CSV)

どの制約が、時間の経過とともにステップスコアに (どのぐらい) 一致するかを確認するには、以下を追加します。

    <problemBenchmarks>
      ...
      <singleStatisticType>CONSTRAINT_MATCH_TOTAL_STEP_SCORE</singleStatisticType>
    </problemBenchmarks>

図14.10 経時ステップスコアの合計に一致する制約統計

constraintMatchTotalStepScoreStatistic

スコア計算が、制約の一致 をサポートする必要があります。Drools スコア計算 では、制約の一致が自動的にサポートされますが、Java インクリメント演算子によるスコア計算 ではさらなる作業が必要です。

警告

制約一致の合計統計は、Solver に大きく影響することが確認されています。

14.6.4. 選択した Move タイプの経時最高スコアの開き統計 (グラフおよび CSV)

どの Move タイプが、時間の経過とともに最高スコアが (どのように) 改善したかを確認するには、以下を追加します。

    <problemBenchmarks>
      ...
      <singleStatisticType>PICKED_MOVE_TYPE_BEST_SCORE_DIFF</singleStatisticType>
    </problemBenchmarks>

図14.11 選択した Move タイプの経時最高スコアの開き統計

pickedMoveTypeBestScoreDiffStatistic

14.6.5. 選択した Move タイプの経時ステップスコアの開き統計 (グラフおよび CSV)

各勝利ステップが、時間の経過とともにステップスコアにどのぐらい影響するかを確認するには、以下を追加します。

    <problemBenchmarks>
      ...
      <singleStatisticType>PICKED_MOVE_TYPE_STEP_SCORE_DIFF</singleStatisticType>
    </problemBenchmarks>

図14.12 選択した Move タイプの経時ステップスコアの開き統計

pickedMoveTypeStepScoreDiffStatistic

14.7. 詳細なベンチマーク

14.7.1. ベンチマークのパフォーマンスに効果的な方法

14.7.1.1. 複数のスレッドで同時に行うベンチマーク

コンピューターで複数のプロセッサーが利用できる場合は、複数のスレッドで同時に複数のベンチマークを実行して、ベンチマークの結果をより速く取得することができます。

<plannerBenchmark>
  ...
  <parallelBenchmarkCount>AUTO</parallelBenchmarkCount>
  ...
</plannerBenchmark>
警告

一度に実行するベンチマークが多すぎると、ベンチマークの結果に悪影響を与えます。ガベージコレクションやその他のプロセスに使用するために、一部のプロセッサーは残すようにしてください。

parallelBenchmarkCountAUTO にすれば、ベンチマーク結果の信頼性と効率が最大になります。

以下の parallelBenchmarkCounts がサポートされます。

  • 1 (デフォルト): すべてのベンチマークを順次実行します。
  • AUTO: 同時に実行するベンチマークの数を Planner が決定します。この計算式は経験に基づいています。その他の並行許可オプションよりも、このオプションを使用することが推奨されます。
  • 統計数: 同時に実行するベンチマークの数。

    <parallelBenchmarkCount>2</parallelBenchmarkCount>
  • JavaScript 計算式: 同時に実行するベンチマークの数を計算する式。availableProcessorCount 変数を使用できます。たとえば、以下のようになります。

    <parallelBenchmarkCount>(availableProcessorCount / 2) + 1</parallelBenchmarkCount>
注記

parallelBenchmarkCount は、常に利用可能なプロセッサー数に制限されます。その値よりも高くなると、自動的に減らされます。

注記

コンピューターの冷却が遅い、または信頼できない場合は、parallelBenchmarkCount を 1 以上 (もしくは AUTO) にすると、CPU がオーバーヒートする可能性があります。

sensors コマンドを使用すれば、オーバーヒートの可能性があることを検出できます。このコマンドは、ほとんどの Linux ディストリビューションでは lm_sensors パッケージまたは lm-sensors パッケージで利用できます。Windows にも無料ソフトが複数利用できます。

注記

今後、複数の JVM ベンチマークをサポートする予定です。この機能は、マルチスレッド解決 またはマルチ JVM 解決とは無関係です。

14.7.2. 統計ベンチマーク

環境と、ベンチマークの結果に対する乱数ジェネレーターへの影響を最小限に抑えるために、ベンチマークを 1 回実行する際に繰り返す回数を設定します。この実行の結果は統計的に集められます。個々の結果については 最高スコア分布の要約 が作成されますが、レポートでも確認できます。

<subSingleCount> 要素を <inheritedSolverBenchmark> 要素、または <solverBenchmark> 要素に追加します。

<?xml version="1.0" encoding="UTF-8"?>
<plannerBenchmark>
  ...
  <inheritedSolverBenchmark>
    ...
    <solver>
      ...
    </solver>
    <subSingleCount>10<subSingleCount>
  </inheritedSolverBenchmark>
  ...
</plannerBenchmark>

subSingleCount のデフォルトは 1 (統計ベンチマークなし) に設定されています。

注記

subSingleCount1 より大きくすると、EnvironmentMode REPRODUCIBLE 以下では、ベンチマーカーが (サブシングルインデックスに対して) 再現性を失わずに、サブシングルの実行に対して、自動的に異なる ランダムシード を使用します。

14.7.3. テンプレートベースのベンチマークと、マトリックスベンチマーク

マトリックスベンチマーキングは、ベンチマーク値を組み合わせて検査を行います。たとえば、ベンチマークの 4 つの entityTabuSize 値 (5711、および 13) と 3 つの acceptedCountLimit 値 (5001000、および 2000) を組み合わせると、Solver 設定は 12 個になります。

このようなベンチマーク設定の詳細レベルを減らすには、ベンチマークの設定に FreeMarker テンプレートを使用することもできます。

<plannerBenchmark>
  ...

  <inheritedSolverBenchmark>
    ...
  </inheritedSolverBenchmark>

<#list [5, 7, 11, 13] as entityTabuSize>
<#list [500, 1000, 2000] as acceptedCountLimit>
  <solverBenchmark>
    <name>entityTabuSize ${entityTabuSize} acceptedCountLimit ${acceptedCountLimit}</name>
    <solver>
      <localSearch>
        <unionMoveSelector>
          <changeMoveSelector/>
          <swapMoveSelector/>
        </unionMoveSelector>
        <acceptor>
          <entityTabuSize>${entityTabuSize}</entityTabuSize>
        </acceptor>
        <forager>
          <acceptedCountLimit>${acceptedCountLimit}</acceptedCountLimit>
        </forager>
      </localSearch>
    </solver>
  </solverBenchmark>
</#list>
</#list>
</plannerBenchmark>

そして、PlannerBenchmarkFactory クラスでビルトします。

        PlannerBenchmarkFactory plannerBenchmarkFactory = PlannerBenchmarkFactory.createFromFreemarkerXmlResource(
                "org/optaplanner/examples/cloudbalancing/benchmark/cloudBalancingBenchmarkConfigTemplate.xml.ftl");
        PlannerBenchmark plannerBenchmark = plannerBenchmarkFactory.buildPlannerBenchmark();

14.7.4. ベンチマークレポート集約

BenchmarkAggregator は、1 つ以上の既存ベンチマークをマージして新しいベンチマークレポートを作成します。ベンチマークが新たに実行することはありません。

benchmarkAggregator

これは、以下に役に立ちます。

  • コード変更の影響をレポート: コード変更の前後で同じベンチマーク設定を実行して、レポートを統合します。
  • 依存関係のアップグレードの影響をレポート: 依存関係のアップグレード前後で同じベンチマーク設定を実行して、レポートを統合します。
  • 詳細なレポートを要約する: 既存レポートの中から、重要な Solver ベンチマークだけを選択します。これは、テンプレートレポートでグラフを読みやすくするのに役に立ちます。
  • ベンチマークを一部再実行: 既存レポートの一部 (たとえば失敗したり無効になっていた Solver だけ) を再実行して、新しい値を使って当初意図したレポートを再作成します。

これを使用するには、PlannerBenchmarkFactoryBenchmarkAggregatorFrame に提供して、GUI を表示します。

    public static void main(String[] args) {
        PlannerBenchmarkFactory plannerBenchmarkFactory = PlannerBenchmarkFactory.createFromXmlResource(
                "org/optaplanner/examples/nqueens/benchmark/nqueensBenchmarkConfig.xml");
        BenchmarkAggregatorFrame.createAndDisplay(plannerBenchmarkFactory);
    }
警告

ベンチマーク設定を入力として使用しているにもかかわらず、その設定で、<benchmarkDirectory> 要素と <benchmarkReport> 要素を除いたすべての要素を無視します。

GUI で、重要なベンチマークだけを選択して、ボタンを押してレポートを作成します。

注記

マージされるすべての入力レポートは、BenchmarkAggregator と同じ Planner バージョンで生成している必要があります (ホットフィックスは同じである必要はありません)。ベンチマークレポートのデータ構造は頻繁に変更するため、メジャーまたはマイナーのバージョンが異なる Planner で作成したレポートでは、正しい情報が提供されていることが保証されません。