Skip to content

Commit

Permalink
Merge pull request #9 from kaityo256/bugfix/8
Browse files Browse the repository at this point in the history
Bugfix/8
  • Loading branch information
kaityo256 authored Feb 25, 2020
2 parents 06e4c46 + 8b1dcc4 commit a609844
Show file tree
Hide file tree
Showing 17 changed files with 30 additions and 19 deletions.
2 changes: 1 addition & 1 deletion day1/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ <h2 id="mpiとは">MPIとは</h2>
<p>一口に「並列化」といっても、様々な種類がありえる。一般に使われている並列プログラミングモデルは、「データ並列」「共有メモリ並列」「分散メモリ並列」の三種類であろう。 以後、プロセスやスレッドといった単語についてかなりいい加減な言葉遣いをするため、ちゃんと学びたい人はちゃんとした書籍を参考にされたい。特にWindowsとLinuxのプロセスの違いとか言い出すと話が長くなるので、ここでは説明しない。また、データ並列についてはとりあえずおいておく。</p>
<p>「共有メモリ並列」とは、並列単位がメモリを共有する並列化方法である。 通常は並列単位としてスレッドを用いるので、ここでは「スレッド並列」と呼ぶ。 逆に「分散メモリ並列」とは、並列単位がメモリを共有しない並列化方法である。 通常は並列単位としてプロセスを用いるので、ここでは「プロセス並列」と呼ぶ。 また、「プロセス並列」と「スレッド並列」を両方行う「ハイブリッド並列」という並列化もある。</p>
<p>まずはプロセスとスレッドの違いについて見てみよう。プロセスとは、OSから見た資源の管理単位である。 プロセスはOSから様々な権限を与えられるが、最も重要なことは「OSから独自のメモリ空間を割り当てられる」ことである。異なるプロセスは異なるメモリ空間を持っており、適切な権限がなければ他のプロセスのメモリを参照できない(そうしないとセキュリティ的に問題がある)。</p>
<p>スレッドとはCPUの利用単位である。通常、一つのCPUコアを利用できるのは一度に一つのスレッドだけである(SMTなどはさておく)。各プロセスは最低一つのスレッドを持っており、プログラムの実行とは、スレッドがCPUコアを使いにいくとである。図解するとこんな感じになる。</p>
<p>スレッドとはCPUの利用単位である。通常、一つのCPUコアを利用できるのは一度に一つのスレッドだけである(SMTなどはさておく)。各プロセスは最低一つのスレッドを持っており、プログラムの実行とは、スレッドがCPUコアを使いにいくことである。図解するとこんな感じになる。</p>
<div class="figure">
<img src="fig/process_thread.png" alt="fig/process_thread.png" />
<p class="caption">fig/process_thread.png</p>
Expand Down
4 changes: 2 additions & 2 deletions day4/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ <h2 id="一次元拡散方程式-シリアル版">一次元拡散方程式 (シ
<p>となる。二次関数で、両端がゼロとなること、これが熱伝導方程式の解になっていることを確認しよう。</p>
<p>計算結果はこんな感じになる。</p>
<div class="figure">
<img src="uniform.png" alt="uniform.png" />
<img src="fig/uniform.png" alt="uniform.png" />
<p class="caption">uniform.png</p>
</div>
<p>時間がたつにつれて温度が上がっていき、定常状態に近づいていくのがわかる。</p>
Expand All @@ -184,7 +184,7 @@ <h2 id="一次元拡散方程式-シリアル版">一次元拡散方程式 (シ
}</code></pre></div>
<p>計算結果はこんな感じ。</p>
<div class="figure">
<img src="fixed.png" alt="fixed.png" />
<img src="fig/fixed.png" alt="fixed.png" />
<p class="caption">fixed.png</p>
</div>
<p>時間がたつにつれて、定常状態である直線になる。ちなみに、定常状態で温度勾配が直線になる現象は<a href="https://ja.wikipedia.org/wiki/%E7%86%B1%E4%BC%9D%E5%B0%8E#%E3%83%95%E3%83%BC%E3%83%AA%E3%82%A8%E3%81%AE%E6%B3%95%E5%89%87">フーリエの法則</a>という名前がついている。あのフーリエ変換のフーリエさんである。もともとフーリエは熱伝導の問題を解くためにフーリエ級数を編み出したのであった。</p>
Expand Down
6 changes: 3 additions & 3 deletions day6/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ perf report

環境によるが、こんな画面が出てくる。

![perf.png](perf.png)
![fig/perf_sample.png](fig/perf_sample.png)

いろいろ出てきているが、とりあえずメインの計算ルーチン`calc`が計算時間の99.36%を占めるのを確認すれば良い。
このように一番「重い」関数のことを **ホットスポット(hotspot)** と呼ぶ。ホットスポットが90%以上を占めるような計算コードはチューニングがやりやすい。
Expand Down Expand Up @@ -602,7 +602,7 @@ $ OMP_NUM_THREADS=2 mpiexec -np 2 ./a.out
これを、手元のスパコンでベンチマークを取ってみよう。石はIntel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz、12コアが2ソケットで1ノードである。
まずは1ノードで、1プロセス1スレッドの計算から、スレッド数だけ2,3,4,6...と増やした場合と、プロセス数だけ2,3,4,6...と増やした場合の結果である。

![single_scaling.png](single_scaling.png)
![fig/single_scaling.png](fig/single_scaling.png)

左が実行時間で両対数、右が並列化効率で片対数グラフになっている。プロセス数を増やした場合、つまりflat-MPIの方が実行効率が良いことがわかる。
24プロセス計算で、シリアル計算に比べて16.6倍、つまり並列化効率にして70%程度出ている。一方、全てスレッド並列で実行した場合も、さほど悪くはないが、
Expand All @@ -614,7 +614,7 @@ $ OMP_NUM_THREADS=2 mpiexec -np 2 ./a.out
1ノードにフルにスレッドを立てると24スレッドなので、18プロセス24スレッドの計算が最小プロセス数である。
横軸にプロセス数、縦軸に実行時間をとった結果が以下の通り。

![multi.png](multi.png)
![fig/multi.png](fig/multi.png)

横軸は対数スケールになっている。全て432スレッドの計算で、違いは「1プロセスが何スレッドを束ねているか」だけなのだが、ここでは432プロセス計算、
すなわち1プロセスが1スレッドだけを持っているflat-MPI計算が最も早かった。
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
12 changes: 6 additions & 6 deletions day6/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ <h2 id="openmpの例">OpenMPの例</h2>
<div class="sourceCode"><pre class="sourceCode sh"><code class="sourceCode bash"><span class="ex">perf</span> report</code></pre></div>
<p>環境によるが、こんな画面が出てくる。</p>
<div class="figure">
<img src="perf.png" alt="perf.png" />
<p class="caption">perf.png</p>
<img src="fig/perf_sample.png" alt="fig/perf_sample.png" />
<p class="caption">fig/perf_sample.png</p>
</div>
<p>いろいろ出てきているが、とりあえずメインの計算ルーチン<code>calc</code>が計算時間の99.36%を占めるのを確認すれば良い。 このように一番「重い」関数のことを <strong>ホットスポット(hotspot)</strong> と呼ぶ。ホットスポットが90%以上を占めるような計算コードはチューニングがやりやすい。</p>
<p>さて、一番重い関数はこんな感じになっている。</p>
Expand Down Expand Up @@ -422,14 +422,14 @@ <h2 id="ハイブリッド並列の実例">ハイブリッド並列の実例</h2
<span class="ex">2</span> 2 4635 [ms]</code></pre></div>
<p>これを、手元のスパコンでベンチマークを取ってみよう。石はIntel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz、12コアが2ソケットで1ノードである。 まずは1ノードで、1プロセス1スレッドの計算から、スレッド数だけ2,3,4,6...と増やした場合と、プロセス数だけ2,3,4,6...と増やした場合の結果である。</p>
<div class="figure">
<img src="single_scaling.png" alt="single_scaling.png" />
<p class="caption">single_scaling.png</p>
<img src="fig/single_scaling.png" alt="fig/single_scaling.png" />
<p class="caption">fig/single_scaling.png</p>
</div>
<p>左が実行時間で両対数、右が並列化効率で片対数グラフになっている。プロセス数を増やした場合、つまりflat-MPIの方が実行効率が良いことがわかる。 24プロセス計算で、シリアル計算に比べて16.6倍、つまり並列化効率にして70%程度出ている。一方、全てスレッド並列で実行した場合も、さほど悪くはないが、 24スレッド計算で、シリアル計算に比べて11.6倍、並列化効率にして48%と、50%を切ってしまう。MPIはバッファを作ったりコピーしたりという手間が発生する分、 マルチスレッドより遅くなりそうだが、今回のケースではflat-MPIの方が早かった。</p>
<p>今度はノードをまたいでみよう。18ノードで計算してみる。各ノードには2ソケットx12コア、合計24コアあるから、全体で18x24=432個のCPUコアがある。 これを、プログラム全体を432スレッドのまま、プロセス数を変えてみよう。例えば、flat-MPIなら1プロセスに1スレッドなので、432プロセスが最大プロセス数、 1ノードにフルにスレッドを立てると24スレッドなので、18プロセス24スレッドの計算が最小プロセス数である。 横軸にプロセス数、縦軸に実行時間をとった結果が以下の通り。</p>
<div class="figure">
<img src="multi.png" alt="multi.png" />
<p class="caption">multi.png</p>
<img src="fig/multi.png" alt="fig/multi.png" />
<p class="caption">fig/multi.png</p>
</div>
<p>横軸は対数スケールになっている。全て432スレッドの計算で、違いは「1プロセスが何スレッドを束ねているか」だけなのだが、ここでは432プロセス計算、 すなわち1プロセスが1スレッドだけを持っているflat-MPI計算が最も早かった。</p>
<p>一般論として、プロセスとスレッドには最適な割合が存在し、どれが一番早いかはやってみないとわからない。 しかし、筆者の経験としては、非常に単純な計算で、かつそこそこ計算量がある場合はflat-MPIが一番早いことが多い。 ただし、筆者はスレッド並列化にあまり慣れていないため、上記のコードもOpenMPに慣れた人がチューニングしたら、もっとハイブリッド版が早くなるのかもしれない。そのあたりはいろいろ試して見てほしい。「こうすればもっと早くなった」「ここが問題だった」といったプルリクを歓迎する。</p>
Expand Down
4 changes: 2 additions & 2 deletions day7/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ $$

磁場中の荷電粒子の運動は、磁場と平行な向きには等速直線運動、垂直な向きには円運動をするため、結果として螺旋を描いてすすむ。こんな感じ。

![magnetic/one.png](magnetic/one.png)
![fig/one.png](fig/one.png)

さて、適当な方向に向いた磁場中に、ランダムな向きに初速を持った荷電粒子たちをばらまいた系を計算してみよう。なお、粒子同士の相互作用も無視する。
三次元シミュレーションなので、三次元ベクトルを構造体で表現する。
Expand Down Expand Up @@ -657,7 +657,7 @@ double energy(void) {

平均エネルギーの時間発展はこうなる。

![magnetic/energy.png](magnetic/energy.png)
![fig/energy.png](fig/energy.png)

1st-Eulerとあるのが1次のオイラー法である。保存するべきエネルギーがどんどん増えてしまっていることがわかる。

Expand Down
File renamed without changes
File renamed without changes
8 changes: 4 additions & 4 deletions day7/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,8 @@ <h2 id="もう少し実戦的なsimd化">もう少し実戦的なSIMD化</h2>
\]</span></p>
<p>磁場中の荷電粒子の運動は、磁場と平行な向きには等速直線運動、垂直な向きには円運動をするため、結果として螺旋を描いてすすむ。こんな感じ。</p>
<div class="figure">
<img src="magnetic/one.png" alt="magnetic/one.png" />
<p class="caption">magnetic/one.png</p>
<img src="fig/one.png" alt="fig/one.png" />
<p class="caption">fig/one.png</p>
</div>
<p>さて、適当な方向に向いた磁場中に、ランダムな向きに初速を持った荷電粒子たちをばらまいた系を計算してみよう。なお、粒子同士の相互作用も無視する。 三次元シミュレーションなので、三次元ベクトルを構造体で表現する。</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">struct</span> vec {
Expand Down Expand Up @@ -464,8 +464,8 @@ <h2 id="もう少し実戦的なsimd化">もう少し実戦的なSIMD化</h2>
}</code></pre></div>
<p>平均エネルギーの時間発展はこうなる。</p>
<div class="figure">
<img src="magnetic/energy.png" alt="magnetic/energy.png" />
<p class="caption">magnetic/energy.png</p>
<img src="fig/energy.png" alt="fig/energy.png" />
<p class="caption">fig/energy.png</p>
</div>
<p>1st-Eulerとあるのが1次のオイラー法である。保存するべきエネルギーがどんどん増えてしまっていることがわかる。</p>
<p>さて、精度を上げる数値積分法はいくらでもあるが、ここでは簡単に二次のRunge-Kutta(RK)法を採用しよう。</p>
Expand Down
Binary file added review/images/day6/multi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added review/images/day6/perf_sample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added review/images/day6/single_scaling.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added review/images/day7/energy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added review/images/day7/one.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 12 additions & 1 deletion review/makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
all: sevendayshpc.pdf
RE=preface.re day1.re day2.re day3.re day4.re day5.re day6.re day7.re postface.re

imgcopy:
cp ../preface/fig/*.png images/preface
cp ../day1/fig/*.png images/day1
cp ../day2/fig/*.png images/day2
cp ../day3/fig/*.png images/day3
cp ../day4/fig/*.png images/day4
cp ../day5/fig/*.png images/day5
cp ../day6/fig/*.png images/day6
cp ../day7/fig/*.png images/day7

preface.md: ../preface/README.md
cp $< $@

Expand Down Expand Up @@ -35,7 +45,8 @@ day7.md: ../day7/README.md
ruby post.rb $*.post > $*.re

sevendayshpc.pdf: config.yml $(RE)
docker run -it --rm -v C:\\Users\\watanabe\\Desktop\\github\\sevendayshpc\\review:/work kauplan/review2.5 /bin/bash -c "cd /work;rake pdf"
docker run --rm -v `pwd`/:/work kauplan/review2.5 /bin/bash -c "cd /work; rake pdf"
#docker run -it --rm -v C:\\Users\\watanabe\\Desktop\\github\\sevendayshpc\\review:/work kauplan/review2.5 /bin/bash -c "cd /work;rake pdf"


clean:
Expand Down

0 comments on commit a609844

Please sign in to comment.