1. 1/68
チューニングとその周辺
Hiroshi Watanabe
Institute for Solid State Physics, University of Tokyo
Collaborators:
Masaru Suzuki (Kyushu University)
Nobuyasu Ito (University of Tokyo)
Outline
1. Introduction
2. Debugging
3. Tunings
4. Publication of Software
5. Summary
Mar. 14, 2012@CMSI 若手技術交流会(合宿) [第五回] 熱海
University of Tokyo
2. 2/68
自己紹介 (1/2)
I’m not a top runner of HPC!
Who are top runners?
ex) Todo-san, Iwata-san, Ishimura-san, etc...
Top runner的なことはそういう人に聞いてください
University of Tokyo
3. 3/68
自己紹介 (2/2)
Q. HPCのtop runnerじゃないならなんなのか?
A. Application Programmer
プログラム歴
小学校 PC-9801F BASIC
中学校から高校 DOSゲー Quick BASIC + アセンブラ
(自分はほとんどアセンブラは組んでない)
大学 Borland C++ Builder Windowsのいわゆるフリーソフトをいくつか作成
大学院 数値シミュレーション Percolation, Event-driven MD、MPI馬鹿パラ
名古屋大学情報科学研究科 ActionScriptでFlashをいくつか作った
東京大学情報基盤センター MPIによる非自明並列化
東京大学物性研究所 いまに至る
University of Tokyo
4. 4/68
これまでに作ったものとか
MS-DOS
ドラクエ型RPG (文化祭用:サブプログラマ、BGM、原画)
対戦アクションゲーム (コンテスト用:サブプログラマ、BGM、原画)
ダンジョンRPG (高校卒業制作:サブプログラム、BGM)
Windows
対戦アクションゲーム (DOSゲーの移植)
パズルゲーム2本
スクリプト言語の統合開発環境
迷路作成プログラム (ヤンメガという漫画の裏表紙になった模様)
量子計算シミュレータQCAD (未踏ソフトウェア採択)
Flash
ミニゲーム
パズルゲーム
その他、交通流シミュレータや物性研クイズなど・・・
University of Tokyo
5. 5/68
渡辺の発言の信頼度
プログラム歴はわりと長い
・プログラム開発方法
・デバッグの方法 ←大丈夫
・「良い」プログラムの書き方
・複数人でのプログラム開発
数値計算歴はさほど長くない
・CPU単体チューニング ←多分大丈夫だが
・メモリマネジメント
一部怪しい気がする
大規模計算は始めたばかり
・MPIによる非自明並列
・大規模計算特有の何か ←かなり怪しい
・国策スパコンについての意見その他
また、フリーソフト作家出身なので、ソフトの公開について意見のバイアスあり
University of Tokyo
8. 8/68
Before optimization
A fast runner is not a good soccer player.
H. Watanabe, 2012
University of Tokyo
9. 9/68
Before optimization
Do not optimize.
最適化するな
H. Matsuo, 2011
University of Tokyo
10. 10/68
Before optimization
Q. 最適化、並列化でもっとも大事なことは何か?
What is the most important thing for optimization?
A. バグを入れないこと
Keep your program from bugs.
University of Tokyo
11. 11/68
Before optimization
バグを入れない方法
いろいろあるが、特に以下の二つの方法が有効
・単体テスト
・sort + diff デバッグ
単体テスト
・テストしようとしている部分だけを切り出す
・その部分だけでコンパイル、動作するような最低限のインターフェース
・最適化、並列化する前と後で結果が一致するかを確認する
・本番環境でテストしない
sort + diff デバッグ
・print文デバッグの一種
・出力情報を保存し、sortしてからdiffを取る
・単体テストと組み合わせて使う
University of Tokyo
18. 18/68
Programming Hierarchy
Parallelization
Network
Parallelization Algorithm
Communication Scheme (OpenMP, MPI)
Memory Transfer
Memory Memory Memory
Cache Efficiency
Reduce Complexity
Tuning
Cache Cache Cache
Specialized Algorithm
to Specific Architecture
assembler, registers, SIMD CPU CPU CPU
Importance: Memory Transfer > Tuning > Parallelization
データ転送がボトルネックになりやすい
University of Tokyo
19. 19/68
CPU (1/2)
RISCと CISC
世の中のCPUアーキテクチャは大別して RISC型とCISC型の二種類
CISC:
・比較的複雑な命令セット
・if分岐などに強い (Out of order 実行)
・Intel Xeon, AMD Opteronなど。
RISC:
・比較的単純な命令セット
・行列演算などに強い
・IBM Power, SPARCなど (京はSPARC VIIIfx)
RISCでOoOだったり、上記の分類に当てはまらないことも多いけど、それはそれ。
マルチコアとSIMD化
最近のCPUはほぼマルチコア化とSIMD化で性能をかせいでいる
・マルチコアで性能を出すには、キャッシュとメモリの構造を把握する必要あり
・SIMDについては後述
University of Tokyo
20. 20/68
CPU (2/2)
ゲーム機とCPU
第六世代
DC SH-4
PS2 MIPS (Emotion Engine), VLIW
GC IBM PowerPC カスタム (Gekko)
Xbox Intel Celeron (PenIII ベース)
第七世代
Wii IBM PowerPC カスタム
Xbox 360 IBM PowerPC カスタム
PS3 IBM Cell 3.2
University of Tokyo
21. 21/68
Memory Hierarchy
Register
FPU
Register
Register
L1 L2 Memory
FPU Register
Floating Processing Unit
CPU
・計算はレジスタ上で行う
・レジスタにのせられた情報はFPUに渡され、レジスタにかえってくる
・メモリアクセスで大事なのは、バンド幅とレイテンシ
Latency
CPUにデータを要求されてから、レジスタに届くまでのサイクル数
・L1キャッシュで数サイクル、L2で10 20サイクル、主記憶は 数百サイクル
Bandwidth
CPUにデータが届き始めてからのデータ転送速度
絶対値(GB/s)よりも、計算速度との比(B/F)の方が良く使われる
University of Tokyo
22. 22/68
レジスタとアセンブリ
アセンブリできること
条件分岐 (if文)
メモリへの読み書き
足し算、引き算、掛け算、割り算 (レジスタ)
レジスタ
CPUが計算や比較などを行うための一時変数
すべての計算、比較は、一度レジスタに値を持ってくる必要がある
京コンピュータは
汎用レジスタ 256個 (めちゃくちゃ多い)ので、レジスタ不足は
とりあえず気にしなくて良い (XeonやPOWERは気にする必要あり)
知っておくべき命令
とりあえずは和、差、積、積和、積差とそのSIMD版、あと三項演算子(fsel系命令)
メモリ管理を考えたらもうちょっと必要かも。
University of Tokyo
30. 30/68
What is Profiler? (Sampler)
Sampler
実行中、一定間隔で「いまどこを実行中か」を調べ、実行時間は
その出現回数に比例すると仮定する
push A
Subroutine Subroutine
A
A
定期的(例えば1ミリ秒に一度)に
pop
いま何が実行中かをカウント
プロファイルオプションつきでコンパイルすると
ルーチンの最初と最後にコードを追加する
C
呼び出しスタック
A
B
B
B
D
Subroutine C
実行中のルーチン
Subroutine B
Subroutine A
Subroutine B
Subroutine B
Subroutine D
Call C
主にHot Spotを探すのに使う
University of Tokyo
31. 31/68
gprof
gprofとは
広く使われるプロファイラ(sampler)
Macでは使えないので GUIプロファイラ「Shark」を使う (Lionには無いそうです・・・)
使い方
$ gcc -pg test.cc
$ ./a.out
$ ls
a.out gmon.out test.cc
$ gprof a.out gmon.out
出力
とりあえず%(割合)だけ見ればいいです
Flat profile:
Each sample counts as 0.01 seconds. サンプリングレートも少しだけ気にすると吉
% cumulative self self total
time seconds seconds calls ms/call ms/call name
100.57 0.93 0.93 1 925.26 925.26 matmat()
0.00 0.93 0.00 1 0.00 0.00 global constructors keyed to A
0.00 0.93 0.00 1 0.00 0.00 __static_initialization_and_destruction_0(int, int)
0.00 0.93 0.00 1 0.00 0.00 init()
0.00 0.93 0.00 1 0.00 0.00 matvec()
0.00 0.93 0.00 1 0.00 0.00 vecvec()
University of Tokyo
32. 32/68
Profile結果の解釈 (Sampler)
一部のルーチンが80%以上の計算時間を占めている
→そのルーチンがホットスポットなので、高速化を試みる
多数のルーチンが計算時間をほぼ均等に使っている
→最適化をあきらめる
あきらめたらそこで試合終了じゃ
ないんですか?
世の中あきらめも肝心です
University of Tokyo
33. 33/68
What is Profiler? (HW Counter)
HW Counter
Hardware Counter
CPUがイベントをカウントする機能を持っている時に使える
イベントとは?
・整数演算
・浮動小数点演算
←こっちに気を取られがちだが
・キャッシュミス
・バリア待ち ←個人的にはこっちが重要だと思う
・演算待ち
HW Counterの使い方
システム依存
カウントするイベントの種類を指定。
プログラムの再コンパイルは不必要
カウンタにより取れるイベントが決まっている
→同じカウンタに割り当てられたイベントが知りたい場合、複数回実行する必要がある
University of Tokyo
34. 34/68
Profile結果の解釈 (HW Counter)
バリア同期待ち
OpenMPのスレッド間のロードインバランスが原因
自動並列化を使ったりするとよく発生
対処:自分でOpenMPを使ってちゃんと考えて書く(それができれば苦労はしないが)
キャッシュ待ち
浮動小数点キャッシュ待ち
対処:メモリ配置の最適化 (連続アクセス、パディング・・・)
ただし、本質的に演算が軽い時には対処が難しい
演算待ち
浮動小数点演算待ち
A=B+C
D=A*E ←この演算は、前の演算が終わらないと実行できない
対処:アルゴリズムの見直し (それができれば略)
SIMD化率が低い
対処できる場合もあるが、あきらめた方がはやいと思う
それでも対処したい人へ:
ループカウンタ間の依存関係を減らしてsoftware pipeliningを促進
University of Tokyo
36. 36/68
仮想メモリとページング (1/2)
Virtual Memory
現在の一般的なOSでは、メモリをページと呼ばれる仮想記憶で管理する。
ハードディスク
仮想メモリ 物理メモリ
(論理メモリ)
論理メモリでは連続に見えても・・・
一部がハードディスクにスワップさ 物理メモリ内では不連続に割り当
れているかもしれない
てられているかもしれない
仮想メモリを使う理由
・不連続なメモリ空間を論理的には連続に見せることができる
仮想メモリなしでは、メモリに余裕があっても連続領域が取れない場合
にメモリ割り当てができないことがある
・スワッピングが可能になる
記憶容量としてハードディスクも使えるため、物理メモリより広い論理
メモリ空間が取れる。
University of Tokyo
37. 37/68
仮想メモリとページング (2/2)
数値計算で何が問題になるか?
F90のallocateや、Cでnew、mallocされた時点では物理メモリの
割り当てがされていない場合がある
real*8, allocatable :: work(:)
allocate (work(10000)) この時点では予約だけされて、まだ物理アドレスが割り当てられない
do i=1, 10000
work(i) = i はじめて触った時点で、メモリがページ単位で割り当てられる
end do
(First touch の原則)
よくある問題:
最初に馬鹿でかい配列を動的に確保しているプログラムの初期化がすごく遅い
・地球シミュレータからT2Kへの移植とかで問題になることが多い。
・OSがLinuxである京でも発生する可能性がある
解決策:
・メモリを静的に確保する(?)
・mallocではなくcallocを使う (Fortranではどうやるのか知りません)
・メモリを確保した直後、ページ単位で全体を触っておく
まぁ、そういうこともあると覚えておいてください
University of Tokyo
38. 38/68
NUMA (1/2)
NUMAとは
非対称メモリアクセス(Non-Uniform Memory Access)の略
CPUにつながっている物理メモリに近いメモリと遠いメモリの区別がある
京コンピュータはNUMAではないが、物性研System BはNUMA
Fast access
Memory
Memory
Memory
CPU
QPI
CPU
Memory
Memory
Memory
Slow access
特にlatency
University of Tokyo
39. 39/68
NUMA (2/2)
数値計算で何が問題になるか?
OpenMPでCPUをまたぐ並列化をする際、初期化を適当にやると
作業領域がコアから遠い物理メモリに割り当てられてしまう
Touch
CORE
CORE
CORE
CORE
QPI
CORE
CORE
CORE
CORE
OpenMPのスレッドを作る前に配列を初期化
→root プロセスの近くにメモリ割り当て
その後OpenMPでスレッド並列
→遠いメモリをアクセス(遅い)
解決策:
スレッドに対応する物理コアに近いところにメモリが割り当てられるように、スレッドごと
に配列を用意した上、OpenMPでスレッド並列化した後にtouchとか
詳しくはNUMA最適化でググれ
University of Tokyo
40. 40/68
Byte / Flop
Byte/Flop
Ratio of memory bandwidth (Byte/s) to computational power (FLOPS)
Usually B/F = 0.1∼0.5
Meaning of B/F
One double precision variable is 64bit, 8 Byte
We need at least two variables to calculate something = 16 Byte
We have to store at least one result = 8 Byte.
We need at least 24 Byte load/store for one calculation.
B/F = 0.5 means that CPU can calculate 48 times during 24 Byte transfer.
If you fetch two double precision variables, you have to calculate
at least 48 times, or CPU will be idle.
Reuse of the fetched data is necessary.
University of Tokyo
41. 41/68
Memory Efficiency (1/2)
Mesh Information
どの空間に粒子が存在するかを多次元配列で実装すると効率が悪い
int GridParticleNumber[GridX][GridY];
int GridParticleIndex[GridX][GridY][GridMax];
Implement by one-dimensional array
O(N) Partial Sort
Cache Efficiency
Latency
University of Tokyo
42. 42/68
Memory Efficiency (2/2)
Pair Information
Since interaction is short-range, we have to construct pair list,
whish is a list of interacting particle-pairs.
Simple Implementation causes,
random access in memory
fetch/store data of two particles per pair
Sorting with particle number
fetch/ store data of one particle per pair
Data of key-particles are on register.
University of Tokyo
43. 43/68
Cache Effieicency (1/2)
Spatial Sorting
University of Tokyo
44. 44/68
Cache Effieicency (2/2)
Efficiency of Spatial Sorting
L2 Cache L3 Cache
(256 KB) (8 MB)
University of Tokyo
45. 45/68
Summary of Memory Management
・CPUチューニングの前にメモリアクセスのチェックを
・とにかくキャッシュにのせる
・メモリアクセスの最適化は、ある種のソートになっていることが多い
(特にPartial Sortは有効であることが多い)
・メモリアクセスの最適化は、計算機を選ばないことが多い
(CPUチューニングはアーキテクチャに強く依存する)
並列化の前にメモリアクセスの最適化をする
・メモリアクセスの最適化をすると、データの持ち方が変わる
→並列化の通信ルーチンが強く影響を受ける
(まぁ、ちゃんと作るならどうせ何度も組み直すことにはなると思う)
・逆にNUMA最適化など、並列化をにらんだデータ構造を持つ必要もある
→要するになんども組み直す必要があるということ
必要なデータがほぼキャッシュに載っており、CPUの
計算待ちがほとんどになって初めてCPUチューニングへ
University of Tokyo
46. 46/68
CPU Tuning
といっても一般的にやれることはあんまりない
University of Tokyo
47. 47/68
Cost of Conditional Branch (1/3)
Benchmark Test
Test code contain only force-calculation (hot-spot).
Effect of conditional branch due to the cutoff.
Condition
L×L×L three-dimensional system.
Free boundary condition
Calculate force between all particle-pairs.
N=20000 (all particles on cache)
(1) Without cutoff
(2) With cutoff (continue)
(3) With cutoff (fsel)
CPU Architecture
Intel Xeon (2.93GHz)
IBM POWER6 (3.5GHz)
University of Tokyo
49. 49/68
Cost of Conditional Branch (3/3)
Elapsed
Time [SEC]
While POWER is faster than Xeon without branch, it becomes
twice slower by twice than Xeon with branch.
Conditional branch is quite expensive for IBM POWER,
since it is in-order execution.
Intel Xeon has branch predictor and it allows us to execute
out-of-order.
University of Tokyo
50. 50/68
Conditional Branch Elimination (1/2)
Conditional Branch Elimination
1. foreach interacting particles
2. r ← particle distance
3. if distance > cutoff length then continue
Very expensive for RISC
4. f ← calculate force
5. p ← update momenta
6. next
1. foreach interacting particles
2. r ← particle distance
3. f ← calculate force
4. if distance > cutoff length then f ←0 fsel in assembler instruction
5. p ← update momenta
6. next
Efficient if the cost of the conditional jump is more
expensive than the additional cost for force calculation.
University of Tokyo
51. 51/68
Conditional Branch Elimination (2/2)
Elapsed
Time [SEC]
IBM Power becomes faster than Xeon using “fsel” built-in function.
if
(r2>CUTOFF)
continue;
df
=
__fsel(r2-CUTOFF,0.0,
df);
fsel
fp0,fp1,fp2,fp3
fp0
=
(fp1
>
0)?
fp2:
fp3;
You
have
to
include
builtins.h
University of Tokyo
52. 52/68
Other kinds of CPU Tuning (1/2)
Division Elimination
1. foreach interacting particles
A1 = 1/B1
2. r2 ← the square of the distance
A2 = 1/B2
3. r6 ← r2*r2*r2
4. r14← r6*r6*2
5. f ← (24.0*r6-48.0)/r14 Division
6. update momenta
D = 1/(B1*B2)
7. next A1 =D*B2
A2 =D*B1
1. foreach particles pairs A,B Doubly Unrolled
2. r14_a ← 14th power of distance of particle pair A
Div. -1
3. r14_b ← 14th power of distance of particle pair B
Mul. +3
4. D = 1/(r14_a * r14_b)
5. f_a ← (24.0*r6_a-48.0) *D*r14_b
6. f_b ← (24.0*r6_b-48.0) *D*r14_a
7. Update momenta
8. next
割り算が「重い」石で有効
University of Tokyo
53. 53/68
Other kinds of CPU Tuning (2/2)
Software Pipelining
Distance
Distance
Distance
Distance
Force
Force
Force
Force
Update Update Update Update
Momenta
Momenta
Momenta
Momenta
Loop Counter
Distance
Distance
Distance
Distance
Force
Force
Force
Update Update
・独立な計算を増やすのが目的 Momenta
Momenta
・条件分岐が含まれるとかなり面倒
・単純なループアンロールはレジスタ不足に陥り易い
・たまにコンパイラが自動でやってくれたりする(ループ方向のSIMD化)
University of Tokyo
54. 54/68
CPU Dependent Tuning Summary
CPU Tunings depend on CPU architecture.
We have to prepare the codes for
architecture to architecture.
世の中には全部intrinsic 命令でホットスポットを書く廃人もいるにはいる
基本的には趣味の世界
University of Tokyo
56. 56/68
作ったプログラムをどうするか
ソフトウェア資産の一生
えらい先生が何かプロジェクトを提案して予算を獲得する
その予算でPDを雇ってプログラムを開発する
プロジェクト終了とともにプログラム開発ストップ
そのまま誰にも使われずに朽ちて行く・・・
なぜそうなるのか?
プログラムは生き物であり、メンテしないと死んでしまう
プログラムのメンテには開発者としての愛着が必要
予算ありきでプログラムを作ると基本的には同じ道を辿る
どうにかできないのか
予算を取ってプログラムを作るのではなく、開発されているプログラムを
予算によって支援する
開発段階からソースを公開する
University of Tokyo
57. 57/68
なぜソースを公開するのか
ソース非公開ということ
ソースが非公開だと、そのプログラムはブラックボックスになる
ブラックボックスのプログラムは
・安定していなければならない
(不正な計算に対してAbortせず、誤った答えを出しても、ユーザはわからない)
・マニュアルが整理されていなければならない
・開発がとまった時がプログラムの死ぬ時
オープンソースソフトウェア
ソースを公開していれば・・・
・ユーザが必要な時に自分で機能変更ができる
・質問があったら「ソース読め」と言える
・開発が止まっても、別の人が開発を引き継ぐ可能性がある
・そのプログラムの一部機能(特に最適化技術)が別のプログラムに
取り込まれていくこともある
University of Tokyo
58. 58/68
ソース公開の難しさ
えらい先生が反対する
せっかくの技術、ノウハウが流出する
→ 技術、ノウハウの流出は分野振興にとって望ましいことのはず
そもそも「サイエンス第一」なんでしょ?
公開は恥ずかしい
自分のプログラムはつたないので、公開するのが恥ずかしい
→公開して恥ずかしくないようなプログラムを組めるように努力する
バグってたら恥ずかしい
→バグってるプログラムで論文書いちゃダメです
公開するためには
最初からソースを公開すると宣言し、賛同する人だけでプロジェクトを開始する
→最初なぁなぁにしておいて、複数人が関わったあとに公開するのは不可能
University of Tokyo
59. 59/68
ソフトウェアの公開方法
公開場所
公開場所として大学のサーバはあまり良くない
→開発者が異動することが多いから
まして年限つきのプロジェクトのサーバに置くのはダメ
→プロジェクト終了後、サーバも消えるかやっかいもの扱いされる運命だから
というわけで、公共のソースコードリポジトリがおすすめ
SourceForge.net, SourceForge.jp, GitHub ...
ソース公開するのがどうしてもイヤ、というならgoogle sitesとか・・・
上記の場所に公開して、プロジェクトや大学のサーバからリンクする
University of Tokyo
60. 60/68
SorceForge.net の例
http://mdacp.sourceforge.net/
http://sourceforge.net/projects/mdacp/stats/
traffic
プロジェクトのウェブページは好きなようにいじることができる
ダウンロード統計も自動で取ってくれる
University of Tokyo
61. 61/68
SorceForge.jp の例
http://qcad.sourceforge.jp/
http://sourceforge.jp/projects/qcad/devel
プロジェクトのウェブページは好きなようにいじることができる
ダウンロード統計も自動で取ってくれる
個人的な意見としては、本家(SF.net)より日本版(SF.jp)の方が使い勝手が良い気がする
University of Tokyo
62. 62/68
GitHubの例
https://github.com/kaityo256/flash/blob/
https://github.com/kaityo256
master/sentos/Sentos.as
ソースが色付きで表示されたりする
gitでアクセスする
無料(有料オプションで、非公開リポジトリを作ることもできる)
簡易SNS的な機能もある(気になる人をTwitterみたいにフォローしたり)
University of Tokyo
63. 63/68
Summary of Software Publication
・アカデミアで開発されたプログラムは、ソースを公開しないと
ほぼ死ぬと思う
・プロジェクトでソフトウェアを作るとだいたいうまくいかない。
・うまくいくのは「もともと作って公開するつもりだったソフトウェア」
をプロジェクトの形で支援、環境を整えること
・プロジェクトの支援とは?
・公開場所を提供することではない
・マンパワーを提供することでもない
・開発者がそのプログラムに集中することを仕事として認めること
University of Tokyo