Upload
yasuhiko-yamamoto
View
793
Download
0
Embed Size (px)
Citation preview
わんくま同盟 名古屋勉強会 #28
C#で、ライフ ゲームを高速化してみるよ
~ 「C#マルチコア本」発刊記念
2013/8/24
BluewaterSoft biac
1
わんくま同盟 名古屋勉強会 #28
スピーカー紹介
2
わんくま同盟 名古屋勉強会 #28
スピーカー紹介 • 1957: スプートニク以前に誕生 (宇宙世紀未満)
• 1983: 名古屋大学工学部(修士)卒
• HONDA R&Dで自動車設計
• 1994~ ソフトウェア業界
• 2012~ BluewaterSoft
biac (山本 康彦)http://www.bluewatersoft.jp
3
わんくま同盟 名古屋勉強会 #28
スピーカー紹介 • 本を書いたり
biac (山本 康彦)http://www.bluewatersoft.jp
速攻入門 C# プログラミング
技術評論社、共著2012/3
Windows 8
業務アプリ開発読本
技術評論社、共著2013/3
C#によるマルチコアのための非同期/並列処理プログラミング
技術評論社2013/7
今日の話は、この第4部から!
4
わんくま同盟 名古屋勉強会 #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
わんくま同盟 名古屋勉強会 #28
スピーカー紹介 • アプリを作ったり
biac (山本 康彦)http://www.bluewatersoft.jp
6
わんくま同盟 名古屋勉強会 #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
わんくま同盟 名古屋勉強会 #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
わんくま同盟 名古屋勉強会 #28
新刊紹介
■はじめにこの本は第一に,.NET Framework で,非同期処理,並列処理を効率良く実現できるマルチスレッドのプログラムを作りたいと思っている開発者のために書きました.
.NET Framework での(マルチスレッドではないプログラムの)開発経験があることを前提にしています.
また,すでにマルチスレッドの経験のあるプログラマーにとっては,ハンドブックとなるように,そして最新の.NET
Framework による効率的なプログラミングを伝えられるようにと書き進めました.
C#によるマルチコアのための
非同期/並列処理プログラミングhttp://www.amazon.co.jp/dp/4774158283/?tag=bluewatersoft-22
9
わんくま同盟 名古屋勉強会 #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
今日の話は、ここから!
わんくま同盟 名古屋勉強会 #28
アプリを高速化する手順
ようやく本題 f(^^;
11
わんくま同盟 名古屋勉強会 #28
一般的には、こんな順序で
非同期化
• 画面とロジックを非同期化
⇒ お互い足を引っ張らないように!
並列化
• ロジックを並列化
⇒ 並列処理にして処理時間を短縮
ロジック
• ロジックを改良してさらに高速化
※先にやっちゃうと、並列化がわけわかめ
12
わんくま同盟 名古屋勉強会 #28
LANGTON'S LOOPS
を高速化してみるよ!
お題
13
わんくま同盟 名古屋勉強会 #28
Langton's loops • セル・オートマトンの一種
• 無限に自己増殖を繰り返す
※ 右はラングトンのループの初期状態。Wikipediaより。
14
わんくま同盟 名古屋勉強会 #28
Langton's loops • ルールに従って、次ステップの状態を計算する
• ルールの例
ラングトンのループは、・セルの状態は0~7
・上下左右の隣のセルと自身の値で次の状態が決まる
15
わんくま同盟 名古屋勉強会 #28
とりあえず見てみるのが早い!
16
わんくま同盟 名古屋勉強会 #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
これは並列化するしか!
でもそれは後のお楽しみ♪
わんくま同盟 名古屋勉強会 #28
画面側
private async Task RunLoops()
{
while (_isRunning)
{
_langtonsLoops.Update(); //ロジックを1ステップ計算させる
UpdateBitmap(_langtonsLoops.Lives); //画面を更新する
await Task.Yield(); // 画面更新の機会を与える(DoEventsの代用)
}
}
18
計算中は画面がフリーズ
画面更新中は計算せず
わんくま同盟 名古屋勉強会 #28
速度計測結果(例) サイクルタイム
性能向上 画面描画速度
最初の実装 0.08秒 --- 12fps
※ あくまでも特定の条件で計測しただけの参考値です
19
わんくま同盟 名古屋勉強会 #28
画面とロジックが足を引っ張り合わないように
まずは非同期化
20
わんくま同盟 名古屋勉強会 #28
画面をフリーズさせない非同期
private async Task RunLoops()
{
while (_isRunning)
{
// await Task.Runで囲って非同期にする
await Task.Run(()=>
_langtonsLoops.Update(); //ロジックを1ステップ計算させる
);
UpdateBitmap(_langtonsLoops.Lives); //画面を更新する
//await Task.Yield(); // DoEvents(の代用)は不要になった
}
}
21
・やっぱりロジックの後で画面更新・やっぱり画面更新中は計算せず
わんくま同盟 名古屋勉強会 #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
わんくま同盟 名古屋勉強会 #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
わんくま同盟 名古屋勉強会 #28
あれっ!? 排他は?
• 2 次元配列 Livesを双方からアクセスする⇒ 排他制御しないとマズイんじゃね?
• よく考えてみる。ロジック: Livesを読み書き画面:Livesから読み出すだけ中途半端に読み出しても、多少画面が乱れるだけ(たぶん誰も気付かない)
⇒ 排他制御しなくていいじゃん!
24
わんくま同盟 名古屋勉強会 #28
速度計測結果(例) サイクルタイム
性能向上 画面描画速度
最初の実装 0.08秒 --- 12fps
非同期化 0.05秒 1.6倍 16fps
※ あくまでも特定の条件で計測しただけの参考値です
25
わんくま同盟 名古屋勉強会 #28
ロジックでマルチ コアをフルに使う
いよいよ並列化
26
わんくま同盟 名古屋勉強会 #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
わんくま同盟 名古屋勉強会 #28
あれっ!? 排他は?
• 2 次元配列 Livesを、複数のスレッドからアクセスする⇒ 排他制御しないとマズイんじゃね?
• よく考えてみる。アクセスする場所は?
r(行)とc(列)で指定された要素。これはスレッドごとに異なる。⇒ 排他制御しなくていいじゃん!
28
わんくま同盟 名古屋勉強会 #28
速度計測結果(例) サイクルタイム
性能向上 画面描画速度
最初の実装 0.08秒 --- 12fps
非同期化 0.05秒 1.6倍 16fps
並列化 0.03秒 2.7倍 8fps
※ あくまでも特定の条件で計測しただけの参考値です
29
わんくま同盟 名古屋勉強会 #28
ロジックを見直してさらに高速化
最後にチューニング
30
わんくま同盟 名古屋勉強会 #28
ロジック自体を高速化
• 2 つのループを 1 つにLives配列を2つ用意して読み出しと書込みを別の配列に。(1ステップごとに交換)
• 観測用の配列を廃止 (単純な変数に)
• ルールの内部表現をスリム化ルール参照キーの生成: 乗算と加算 ⇒ ビット演算その他いろいろ
31
わんくま同盟 名古屋勉強会 #28
速度計測結果(例) サイクルタイム
性能向上 画面描画速度
最初の実装 0.08秒 --- 12fps
非同期化 0.05秒 1.6倍 16fps
並列化 0.03秒 2.7倍 8fps
チューン 0.01秒 8倍 10fps
※ あくまでも特定の条件で計測しただけの参考値です
32
わんくま同盟 名古屋勉強会 #28
大事な事なのでもういちど
以上、完了
33
わんくま同盟 名古屋勉強会 #28
一般的には、こんな順序で
非同期化
• 画面とロジックを非同期化
⇒ お互い足を引っ張らないように!
並列化
• ロジックを並列化
⇒ 並列処理にして処理時間を短縮
ロジック
• ロジックを改良してさらに高速化
※先にやっちゃうと、並列化がわけわかめ
34
+ 排他制御は、よくよく考えて!
※不要なことも多い。ムダな排他は低速化とバグの元
わんくま同盟 名古屋勉強会 #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
わんくま同盟 名古屋勉強会 #28
ご清聴ありがとうございました
36