3. チューニングの作業内容と結果

本章では、2.2節( チューニング手順 )の手順にそって実施したチューニングの内容と結果について紹介します。

3.1. 実行時間の計測

チューニング実施前に本アプリケーションの実行時間を計測しました。 チューニング効果の検証などで用いるために、本アプリケーションに組み込まれていた時刻の出力ログを利用して、実行時間をいくつかの計測区間に分けました。本文書では本アプリケーションの実行時間を表示する際は、アプリケーション全体の実行時間に加えて、各計測区間の実行時間も表示します。

主な計測区間は、「ソルバー」・「制限関数処理」・「その他」の3つです。そのうち「その他」は、アプリケーション全体の実行時間から、それ以外の2つの実行時間を差し引いたものです。

さらに「ソルバー」は、処理内容の違いから「システム方程式マトリクス計算」・「システム方程式マトリクス構築」・「システム方程式以外の方程式処理」・「ソルバーのその他」に分かれます。そのうち「ソルバーのその他」は「ソルバー」の実行時間から、それ以外の3つの実行時間を差し引いたものです。

計測したアプリケーション全体の実行時間と、計測区間ごとの実行時間は下表の通りです。下表によると最も実行時間が長い計測区間は「システム方程式マトリクス計算」で、全体の約43%を占めています。

../_images/table1.png

3.2. 関数単位のコストの計測

チューニング実施前に富士通製プロファイラ(基本プロファイラ)を利用して関数単位のコストをサンプリング解析にて、計測しました。基本プロファイラの計測結果には1645個の関数とそのコストが出力されました。関数単位のコストはその実行時間に比例し、チューニング対象を選択する際の参考になります。

下表は基本プロファイラの計測結果のうち、コストの高い順に上位10個の関数を抜粋したものです。「計測区間名」のカラムは当該関数がどの計測区間に含まれているかを示しています。「コスト」のカラムは基本プロファイラが出力した関数単位のコストです。「コストの割合」のカラムは、アプリケーション全体のコストに対する各関数単位のコストの割合を示し、「コストの割合の累積」のカラムは、各関数単位のコストの割合をコストの高い順に1番目の関数から当該関数まで足し合わせた結果です。

関数名

計測区間名

コスト

コストの割合[%]

コストの割合の累積[%]

0

(アプリケーション全体)

10145395

100.00

1

calc_function_1

システム方程式マトリクス計算

2359630

23.26

23.26

2

function_of_MPI_1

(プロセス間通信)

1818309

17.92

41.18

3

function_of_MPI_2

(プロセス間通信)

1090237

10.75

51.93

4

make_function_1

システム方程式マトリクス構築

359086

3.54

55.47

5

make_function_2

システム方程式マトリクス構築

323755

3.19

58.66

6

limiter_function_1

制限関数処理

290204

2.86

61.52

7

calc_function_2

システム方程式マトリクス計算

187961

1.85

63.37

8

make_function_3

システム方程式マトリクス構築

176418

1.74

65.11

9

calc_function_3

システム方程式マトリクス計算

165032

1.63

66.74

10

make_function_4

システム方程式マトリクス構築

156562

1.54

68.28

上位3個の関数のコストはすべて10%を超え、3つ合わせてアプリケーション全体のコストの50%以上を占めています。最もコストが高い関数は「システム方程式マトリクス計算」の計測区間に含まれる calc_function_1 関数で、全体の約23%を占めています。次にコストが高いのは function_of_MPI_1 関数と function_of_MPI_2 関数ですが、プロセス間通信の関数でありチューニング対象にはなりません。

一方、4位以下の関数のコストをみると、4位の時点で全体の3.54%、10位の時点で1.54%まで低下しており、コストが多くの関数に分散していることがわかります。

3.3. チューニングの実施

前述の手順と計測結果に基づいて、チューニングを実施しました。本節ではその内容と結果を紹介します。

3.3.1. チューニング項目の一覧

下表は、本アプリケーションに対して実施した全てのチューニング項目の内容と対象関数を示したものです。各チューニング項目は実施した順に並んでおり、その内容としてチューニングの概要・方法・狙いと、対象関数、および対象関数が含まれる計測区間を示しています。4章( チューニング項目 )ではこの中から10個のチューニング項目を抜粋して詳しく説明します。

下表の「チューニングの方法」のカラムでは、最適化制御行の追加や、翻訳時オプションの変更など、チューニングの実施手法を簡単に記載しています。また、「チューニングの狙い」のカラムでは、チューニングを実施する際に意図した改善点などを記載しています。この「チューニングの狙い」のカラムは、「富岳」の利用者ポータルに掲載されている『プログラミングガイド チューニング編』の目次の大項目を参考にしたものです。

項番

チューニングの概要

チューニングの方法

チューニングの狙い

対象関数

対象関数が含まれる処理区間名

本文書での記載箇所

1

小回転ループの一重化およびループ展開

ソースコード変更

命令数の削減

calc_function_1

システム方程式マトリクス計算

2

プリフェッチ命令の発行

最適化制御行の追加のみ

レイテンシの隠蔽によるデータアクセス待ち改善

calc_function_1

システム方程式マトリクス計算

3

ループ内の配列足し込みの連続アクセス化

ソースコード変更

レイテンシの隠蔽によるデータアクセス待ち改善

calc_function_1

システム方程式マトリクス計算

4

ループ展開

ソースコード変更

命令数の削減、ループ最適化による命令スケジューリングの改善

calc_function_1

システム方程式マトリクス計算

5

ループ展開

ソースコード変更

命令数の削減、ループ最適化による命令スケジューリングの改善

calc_function_1

システム方程式マトリクス計算

6

faddv命令の抑止

翻訳時オプション変更

命令数の削減

calc_function_1

システム方程式マトリクス計算

7

ループ展開

最適化制御行の追加のみ

命令数の削減、ループ最適化による命令スケジューリングの改善

make_function_2

システム方程式マトリクス構築

make_function_3

システム方程式マトリクス構築

8

マトリクスの非対角項を並び替え

ソースコード変更

連続アクセス化

calc_function_1

システム方程式マトリクス計算

9

小回転ループのSIMD化抑止

最適化制御行の追加のみ

命令数の削減

calc_function_3

システム方程式マトリクス計算

make_function_1

システム方程式マトリクス構築

make_function_4

システム方程式マトリクス構築

make_function_5

システム方程式マトリクス構築

make_function_6

システム方程式マトリクス構築

10

除算処理のSIMD化と小回転ループのSIMD化抑止

ソースコード変更

SIMD化の促進による演算待ち改善

calc_function_3

システム方程式マトリクス計算

4.1節

11

ループ展開によるload/store削減

ソースコード変更

命令数の削減、ループ最適化による命令スケジューリングの改善

calc_function_1

システム方程式マトリクス計算

4.2節

12

ループアンスイッチング

最適化制御行の追加のみ

レイテンシの隠蔽によるデータアクセス待ち改善

make_function_5

システム方程式マトリクス構築

13

ループ展開

最適化制御行の追加のみ

命令数の削減、ループ最適化による命令スケジューリングの改善

make_function_2

システム方程式マトリクス構築

14

領域分割のパラメータ変更

実行時の設定変更

MPI並列計算のプロセス間負荷バランスを向上

15

余分な型変換の削減

ソースコード変更

命令数の削減

make_function_2

システム方程式マトリクス構築

16

ループ一重化によるSIMD化促進

ソースコード変更

SIMD化の促進による演算待ち改善

make_function_6

システム方程式マトリクス構築

4.3節

17

ループ分割によるSIMD化促進

ソースコード変更

SIMD化の促進による演算待ち改善

make_function_2

システム方程式マトリクス構築

18

インライン展開

ソースコード変更

命令数の削減

limiter_function_1

制限関数処理

make_function_1

システム方程式マトリクス構築

make_function_4

システム方程式マトリクス構築

make_function_9

システム方程式マトリクス構築

calc_function_2

システム方程式マトリクス計算

calc_function_3

システム方程式マトリクス計算

calc_function_5

システム方程式マトリクス計算

19

ループ回転方向変更

ソースコード変更

レイテンシの隠蔽によるデータアクセス待ち改善

othSolv_function_3

システム方程式以外の方程式処理

4.4節

20

不変式の移動

ソースコード変更

レイテンシの隠蔽による演算待ち改善

make_function_8

システム方程式マトリクス構築

21

ループ分割

ソースコード変更

命令数の削減、ループ最適化による命令スケジューリングの改善

make_function_8

システム方程式マトリクス構築

22

ループ内配列のレジスタ化

ソースコード変更

レイテンシの隠蔽によるデータアクセス待ち改善

make_function_8

システム方程式マトリクス構築

23

計算式のコスト削減

ソースコード変更

命令数の削減

make_function_8

システム方程式マトリクス構築

24

SVE ACLEによるSIMD化

ソースコード変更

SIMD化の促進による演算待ち改善

calc_function_4

システム方程式マトリクス計算

4.5節

25

ビルトインプリフェッチ

ソースコード変更

レイテンシの隠蔽によるデータアクセス待ち改善

make_function_2

システム方程式マトリクス構築

4.6節

make_function_3

システム方程式マトリクス構築

make_function_7

システム方程式マトリクス構築

26

SIMD化促進のための配列静的確保

ソースコード変更

SIMD化の促進による演算待ち改善

calc_function_1

システム方程式マトリクス計算

27

クローンチューニングおよびループ展開

ソースコード変更

レイテンシの隠蔽によるデータアクセス待ち改善

make_function_6

システム方程式マトリクス構築

make_function_12

システム方程式マトリクス構築

28

除算処理をループの外側に移動しSIMD化

ソースコード変更

SIMD化の促進による演算待ち改善

make_function_7

システム方程式マトリクス構築

4.7節

29

ビルトインプリフェッチ

ソースコード変更

レイテンシの隠蔽によるデータアクセス待ち改善

othSolv_function_1

システム方程式以外の方程式処理

othSolv_function_2

システム方程式以外の方程式処理

othSolv_function_5

システム方程式以外の方程式処理

30

インライン展開によるSIMD化促進

ソースコード変更

SIMD化の促進による演算待ち改善

function_1

システム方程式以外の方程式処理

function_2

システム方程式以外の方程式処理

31

スレッド並列化

ソースコード変更

スレッド並列チューニング

calc_function_1

システム方程式マトリクス計算

make_function_7

システム方程式マトリクス構築

32

load命令のスケジューリング改善

ソースコード変更

ループ最適化による命令スケジューリングの改善

othSolv_function_4

システム方程式以外の方程式処理

33

ループ外への不変式の移動

ソースコード変更

ループ最適化による命令スケジューリングの改善

calc_function_2

システム方程式マトリクス計算

4.8節

34

最適化制御行を使わないループ展開

ソースコード変更

命令数の削減、ループ最適化による命令スケジューリングの改善

calc_function_4

システム方程式マトリクス計算

4.9節

35

ループ内配列のレジスタ化

ソースコード変更

レイテンシの隠蔽によるデータアクセス待ち改善

calc_function_4

システム方程式マトリクス計算

calc_function_5

システム方程式マトリクス計算

36

ループインターリーブ

ソースコード変更

レイテンシの隠蔽による演算待ち改善

calc_function_1

システム方程式マトリクス計算

37

余分な型変換の削減

ソースコード変更

命令数の削減

calc_function_1

システム方程式マトリクス計算

38

プリフェッチ命令の発行

ソースコード変更

レイテンシの隠蔽によるデータアクセス待ち改善

calc_function_1

システム方程式マトリクス計算

39

ループ一重化

ソースコード変更

ループ最適化による命令スケジューリングの改善

make_function_6

システム方程式マトリクス構築

make_function_5

システム方程式マトリクス構築

40

クローンチューニングおよびインライン展開

ソースコード変更

命令数の削減、ループ最適化による命令スケジューリングの改善

make_function_6

システム方程式マトリクス構築

make_function_5

システム方程式マトリクス構築

make_function_7

システム方程式マトリクス構築

41

2次元配列のメモリ配置改善

ソースコード変更

連続アクセス化

allocate_array

(アプリケーション全体)

4.10節

clear_array

(アプリケーション全体)

deallocate_array

(アプリケーション全体)

reallocate_array

(アプリケーション全体)

allocate_array_2

(アプリケーション全体)

deallocate_array_2

(アプリケーション全体)

reallocate_array_2

(アプリケーション全体)

42

項番41の改善をベースとしたSIMD化の改善

ソースコード変更

SIMD化の促進による演算待ち改善

calc_function_1

システム方程式マトリクス計算

43

クローンチューニング

ソースコード変更

ループ最適化による命令スケジューリングの改善

make_function_7

システム方程式マトリクス構築

44

ビルトインプリフェッチ箇所のSIMD化抑止

最適化制御行の追加のみ

命令数の削減

make_function_7

システム方程式マトリクス構築

上表の44個のチューニング項目のうち、本文書では、以下のような特徴を持つ10個のチューニング項目を4章( チューニング項目 )で紹介します。

3.3.2. アプリケーションの改善結果

以下は、チューニングを実施する前と、前述の全てのチューニング項目(項番1から44まで)を実施した後の、実行時間および性能改善率です。チューニング実施後のアプリケーション全体の性能改善率は58%に達し、実行時間はチューニング実施前の半分以下になり、目標を達成しました。

../_images/table4.png

本アプリケーションへのチューニングでは、3.3.1項( チューニング項目の一覧 )の44個のチューニング項目を上から順に実施する過程で、アプリケーションの性能を複数回計測しました。以下のグラフは、アプリケーション全体および各計測区間について、実行時間と、チューニング実施前に対する性能改善率が、チューニング項目によってどのように推移したかを示しています。なお、以下のグラフの実行時間は各計測区間の積み上げグラフで、縦棒の高さと上部の数字はアプリケーション全体の実行時間を示します。

両グラフの横軸は、ともに3.3.1項( チューニング項目の一覧 )のチューニング項目の項番1から該当番号までの項番を実施した後に計測した結果を表します。たとえば、横軸8の位置にあるデータは、チューニング項目の項番8まで(項番1から8)を実施した後の計測結果です。ただし、横軸0の位置にあるデータは、チューニング実施前のデータです。

../_images/image1.png

上記グラフによると、チューニング項目の項番1から13までで、アプリケーション全体の性能は約34%改善し、「システム方程式マトリクス計算」の性能は約68%改善しました。ここでは、基本プロファイラのコストが高い順に関数を選択・分析し、項番13までのチューニング項目では上位8個までの関数にチューニングを実施しました。実施した13個のチューニング項目のうち7個は、最もコストが高い calc_function_1 関数を対象としたチューニングです。

項番14では、アプリケーション全体の性能が約6%改善しました。項番14は、領域分割のパラメータ変更によるプロセス間の負荷バランスの向上です。これはアプリケーションを開発した ISV の知見に基づき、問題点および改善策を洗い出した結果です。

項番15から44までで、アプリケーション全体の性能がさらに約18%向上しました。ここでは、主に低コスト関数をチューニングの対象としたため、チューニング1項目あたりのアプリケーション全体への性能改善率が項番14までと比べて小さくなりました。

また、計測区間ごとの性能改善率をみると、項番1から13は「システム方程式マトリクス計算」、項番14は「ソルバーのその他」、項番15から26は主に「制限関数処理」、項番28から30は「システム方程式以外の方程式処理」に、大きく寄与しています。

最終的には、アプリケーション全体の約52%を占める上位30個までの関数(チューニング対象外のプロセス間通信の関数を除く)を選択・分析し実施した40個のチューニング項目、プロセス間の負荷バランス向上のチューニング項目、スレッド並列化のチューニング項目、コストは低いが多くの関数で利用される関数への2個のチューニング項目(そのうち1つは 4.10節( 2次元配列のメモリ配置改善 )で紹介)、の合計44個のチューニング項目を実施しました。結果として、アプリケーション全体の実行時間が、202.9秒から85.0秒に短縮(約2.4倍の高速化)し、当初の目標(2倍以上の高速化)を達成しました

「富岳」での大規模シミュレーションを実現するために

チューニング項目のうち項番14と項番31は、利用者が求める大規模なシミュレーションを行う際に、数十万並列の計算リソースを活用するために特に重要となる項目です。

項番14:領域分割のパラメータ変更

項番14では、MPI 並列計算のプロセス間負荷バランスを向上させるために、本アプリケーション内で設定されている領域分割のパラメータを変更しました。負荷バランスが悪いとプロセス間の通信待ち時間が長くなり、並列数が増えるほどその影響が大きくなります。そのため、プロセス間で計算量をできるだけ均等に分配することは重要なポイントです。

項番31:スレッド並列化

本アプリケーションは、当初スレッド並列に対応していませんでした。しかし、利用者が求めるような数十万並列のシミュレーションを、計算リソースをなるべく効率的に活用して行うためには、スレッド並列は重要な項目になります。そこでチューニングの1つとして、初めてスレッド並列化を行いました。まず今回のチューニングでは、データ競合などの阻害要因がなく比較的に取り組みやすい、calc_function_1 関数と make_function_7 関数(チューニング実施前の関数コストの割合は、2つ合わせて全体の約25%)に限定して、スレッド並列化を行いました。

数十万並列の大規模な計算に比べると、今回のチューニングの性能評価で行った計算は小規模でした。そのため、上記2項目を含む全てのチューニング項目を実施したのち、約8億要素を持つ大規模モデルを用いて、「富岳」で動作検証を行いました。「富岳」の4000ノード超の計算リソースを使い、MPI 並列とスレッド並列(スレッド数4)を組み合わせたハイブリッド並列によって、約22万並列までの動作を確認し、さらに約20万並列までの速度向上が確認できました。これは、上記2項目を含む今回のチューニングによる成果で、今後スレッド並列化の対象範囲拡大などさらなる改善を行うことで、より大規模なシミュレーションも実現できると考えています。