36
わんくま同盟 名古屋勉強会 #28 C#で、ライフ ゲームを高速化してみるよ ~「C#マルチコア本」発刊記念 2013/8/24 BluewaterSoft biac 1

わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

Embed Size (px)

Citation preview

Page 1: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

C#で、ライフ ゲームを高速化してみるよ

~ 「C#マルチコア本」発刊記念

2013/8/24

BluewaterSoft biac

1

Page 2: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

スピーカー紹介

2

Page 3: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

スピーカー紹介 • 1957: スプートニク以前に誕生 (宇宙世紀未満)

• 1983: 名古屋大学工学部(修士)卒

• HONDA R&Dで自動車設計

• 1994~ ソフトウェア業界

• 2012~ BluewaterSoft

biac (山本 康彦)http://www.bluewatersoft.jp

3

Page 4: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

スピーカー紹介 • 本を書いたり

biac (山本 康彦)http://www.bluewatersoft.jp

速攻入門 C# プログラミング

技術評論社、共著2012/3

Windows 8

業務アプリ開発読本

技術評論社、共著2013/3

C#によるマルチコアのための非同期/並列処理プログラミング

技術評論社2013/7

今日の話は、この第4部から!

4

Page 5: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

スピーカー紹介 • 記事を書いたり

biac (山本 康彦)http://www.bluewatersoft.jp WinRT/Metro TIPS

@IT ~ 連載中http://www.atmarkit.co.jp/ait/subtop/features/da/ap_winrttips_index.html

C#で始めるテスト駆動開発入門

CodeZinehttp://codezine.jp/article/corner/446

特集: 次期 Windows 8.1 &

Visual Studio 2013

Preview 概説

@IT 2013/7http://www.atmarkit.co.jp/ait/articles/1307/19/news099.html

5

Page 6: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

スピーカー紹介 • アプリを作ったり

biac (山本 康彦)http://www.bluewatersoft.jp

6

Page 7: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

スピーカー紹介 • 講師やったりしてます

biac (山本 康彦)http://www.bluewatersoft.jp

C# / VB.NET による

Windows 8 アプリ開発入門

2013/10/30~31名古屋ソフトウェアセンター

http://www.nagoya-sc.co.jp/ap/seminar?m=1&key=10734

7

Page 8: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

新刊紹介

• 2013/7/20上梓

• 電子書籍版もありますhttps://gihyo.jp/dp/ebook/2013/978-4-7741-5907-2

• C#はやってるけど、非同期/並列処理は「?」という開発者に!

C#によるマルチコアのための

非同期/並列処理プログラミングhttp://www.amazon.co.jp/dp/4774158283/?tag=bluewatersoft-22

8

Page 9: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

新刊紹介

■はじめにこの本は第一に,.NET Framework で,非同期処理,並列処理を効率良く実現できるマルチスレッドのプログラムを作りたいと思っている開発者のために書きました.

.NET Framework での(マルチスレッドではないプログラムの)開発経験があることを前提にしています.

また,すでにマルチスレッドの経験のあるプログラマーにとっては,ハンドブックとなるように,そして最新の.NET

Framework による効率的なプログラミングを伝えられるようにと書き進めました.

C#によるマルチコアのための

非同期/並列処理プログラミングhttp://www.amazon.co.jp/dp/4774158283/?tag=bluewatersoft-22

9

Page 10: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

新刊紹介

■目次Part 1 マルチコアのための非同期処理/並列処理の原理

Chapter 1 マルチコアを使いこなす非同期処理/ 並列処理の時代

Chapter 2 試して納得!マルチコア活用プログラミングの原理とポイント

Part 2 マルチコアを使いこなすための非同期/並列処理必須知識

Part 3 マルチコアのためのC#/.NETの非同期/並列処理の方法

Part 4 マルチコア非同期/並列処理実践プログラミング

C#によるマルチコアのための

非同期/並列処理プログラミングhttp://www.amazon.co.jp/dp/4774158283/?tag=bluewatersoft-22

10

今日の話は、ここから!

Page 11: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

アプリを高速化する手順

ようやく本題 f(^^;

11

Page 12: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

一般的には、こんな順序で

非同期化

• 画面とロジックを非同期化

⇒ お互い足を引っ張らないように!

並列化

• ロジックを並列化

⇒ 並列処理にして処理時間を短縮

ロジック

• ロジックを改良してさらに高速化

※先にやっちゃうと、並列化がわけわかめ

12

Page 13: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

LANGTON'S LOOPS

を高速化してみるよ!

お題

13

Page 14: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

Langton's loops • セル・オートマトンの一種

• 無限に自己増殖を繰り返す

※ 右はラングトンのループの初期状態。Wikipediaより。

14

Page 15: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

Langton's loops • ルールに従って、次ステップの状態を計算する

• ルールの例

ラングトンのループは、・セルの状態は0~7

・上下左右の隣のセルと自身の値で次の状態が決まる

15

Page 16: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

とりあえず見てみるのが早い!

16

Page 17: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

ロジック側

public class LangtonsLoops {

//「世界」(intの2次元配列)

int[,] _lives;

public int[,] Lives { get { return _lives; } }

// セルオートマトンの規則

Rule _rule;

public void Update() {

// 隣を見る(観測し終わるまで_livesを変更してはいけない)

for (int r = 1; r < _size - 1; r++)

for (int c = 1; c < _size - 1; c++)

//…

// 次ステップの状態を計算して_livesを書き換える

for (int r = 1; r < _size - 1; r++)

for (int c = 1; c < _size - 1; c++)

//…

}

}

17

これは並列化するしか!

でもそれは後のお楽しみ♪

Page 18: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

画面側

private async Task RunLoops()

{

while (_isRunning)

{

_langtonsLoops.Update(); //ロジックを1ステップ計算させる

UpdateBitmap(_langtonsLoops.Lives); //画面を更新する

await Task.Yield(); // 画面更新の機会を与える(DoEventsの代用)

}

}

18

計算中は画面がフリーズ

画面更新中は計算せず

Page 19: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

速度計測結果(例) サイクルタイム

性能向上 画面描画速度

最初の実装 0.08秒 --- 12fps

※ あくまでも特定の条件で計測しただけの参考値です

19

Page 20: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

画面とロジックが足を引っ張り合わないように

まずは非同期化

20

Page 21: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

画面をフリーズさせない非同期

private async Task RunLoops()

{

while (_isRunning)

{

// await Task.Runで囲って非同期にする

await Task.Run(()=>

_langtonsLoops.Update(); //ロジックを1ステップ計算させる

);

UpdateBitmap(_langtonsLoops.Lives); //画面を更新する

//await Task.Yield(); // DoEvents(の代用)は不要になった

}

}

21

・やっぱりロジックの後で画面更新・やっぱり画面更新中は計算せず

Page 22: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

ロジックを全速力で走らせる非同期(1/2)

public class LangtonsLoops { // ロジック側

// 変更を画面に通知するためのイベント

public event PropertyChangedEventHandler PropertyChanged;

public async Task RunLoopsAsync() {

// フラグが立っている間、非同期で計算し続ける

await Task.Run(() => {

while (_isRunning) {

Update();

if (this.PropertyChanged != null)

this.PropertyChanged(this, new PropertyChangedEventArgs("Lives"));

}

});

//…

}

// ……以下略……

22

Page 23: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

ロジックを全速力で走らせる非同期(2/2)

public sealed partial class MainPage : LayoutAwarePage { // 画面側

// ロジックを起動する

private async Task RunLoops() {

//…

await _langtonsLoops.RunLoopsAsync();

}

// ロジックから呼び出されるイベントハンドラー

async void LangtonsLoops_PropertyChanged(object sender, PropertyChangedEventArgs e) {

if (e.PropertyName == "Lives") {

//…UpdateBitmapしてるときは、イベントを無視してここでリターン…

await _thisDispatcher.RunAsync( // UIスレッドで実行する

Windows.UI.Core.CoreDispatcherPriority.Normal,

() => { UpdateBitmap(_langtonsLoops.Lives); //…

});

//…

}

}

// ……以下略……

23

Page 24: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

あれっ!? 排他は?

• 2 次元配列 Livesを双方からアクセスする⇒ 排他制御しないとマズイんじゃね?

• よく考えてみる。ロジック: Livesを読み書き画面:Livesから読み出すだけ中途半端に読み出しても、多少画面が乱れるだけ(たぶん誰も気付かない)

⇒ 排他制御しなくていいじゃん!

24

Page 25: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

速度計測結果(例) サイクルタイム

性能向上 画面描画速度

最初の実装 0.08秒 --- 12fps

非同期化 0.05秒 1.6倍 16fps

※ あくまでも特定の条件で計測しただけの参考値です

25

Page 26: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

ロジックでマルチ コアをフルに使う

いよいよ並列化

26

Page 27: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

ロジックを並列化する

public class LangtonsLoops {

//……省略……

public void Update() {

// 隣を見る(観測し終わるまで_livesを変更してはいけない)

Parallel.For(1, _size - 1, (r) => {

for (int c = 1; c < _size - 1; c++) {

//……隣を観測してメモリに保持……

}

});

// 次ステップの状態を計算して_livesを書き換える

Parallel.For(1, _size - 1, (r) => {

for (int c = 1; c < _size - 1; c++) {

//……隣の観測結果から、次ステップを計算し、_livesに書き込み

}

});

}

27

Page 28: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

あれっ!? 排他は?

• 2 次元配列 Livesを、複数のスレッドからアクセスする⇒ 排他制御しないとマズイんじゃね?

• よく考えてみる。アクセスする場所は?

r(行)とc(列)で指定された要素。これはスレッドごとに異なる。⇒ 排他制御しなくていいじゃん!

28

Page 29: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

速度計測結果(例) サイクルタイム

性能向上 画面描画速度

最初の実装 0.08秒 --- 12fps

非同期化 0.05秒 1.6倍 16fps

並列化 0.03秒 2.7倍 8fps

※ あくまでも特定の条件で計測しただけの参考値です

29

Page 30: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

ロジックを見直してさらに高速化

最後にチューニング

30

Page 31: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

ロジック自体を高速化

• 2 つのループを 1 つにLives配列を2つ用意して読み出しと書込みを別の配列に。(1ステップごとに交換)

• 観測用の配列を廃止 (単純な変数に)

• ルールの内部表現をスリム化ルール参照キーの生成: 乗算と加算 ⇒ ビット演算その他いろいろ

31

Page 32: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

速度計測結果(例) サイクルタイム

性能向上 画面描画速度

最初の実装 0.08秒 --- 12fps

非同期化 0.05秒 1.6倍 16fps

並列化 0.03秒 2.7倍 8fps

チューン 0.01秒 8倍 10fps

※ あくまでも特定の条件で計測しただけの参考値です

32

Page 33: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

大事な事なのでもういちど

以上、完了

33

Page 34: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

一般的には、こんな順序で

非同期化

• 画面とロジックを非同期化

⇒ お互い足を引っ張らないように!

並列化

• ロジックを並列化

⇒ 並列処理にして処理時間を短縮

ロジック

• ロジックを改良してさらに高速化

※先にやっちゃうと、並列化がわけわかめ

34

+ 排他制御は、よくよく考えて!

※不要なことも多い。ムダな排他は低速化とバグの元

Page 35: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

今日のネタ

• 今日のソースコードgihyo.jpのサポートページにあります

http://gihyo.jp/book/2013/978-4-

7741-5828-0/support

C#によるマルチコアのための

非同期/並列処理プログラミングhttp://www.amazon.co.jp/dp/4774158283/?tag=bluewatersoft-22

35

Page 36: わんくま名古屋#28(20130824) c#で、ライフゲームを高速化してみるよ

わんくま同盟 名古屋勉強会 #28

ご清聴ありがとうございました

36