Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
C# ドキドキ・ライブコーディング
~ 小島の分 ~
BuriKaigi2019 – 富山合同勉強会
2019/01/26
小島 富治雄
#burikaigi
自己紹介
 小島 富治雄
 @Fujiwo
 福井コンピュータアーキテクト株式会社
 Microsoft MVP (2005-2019) C#関連
これまでの
対戦
BuriKaigi2019 https://connpass.com/event/111062/
#BuriKaigi 2
この写真 の作成者 不明な作成者 は CC BY-SA のライセンスを許諾されています
2015年のお題「七ならべ」のときに
思いついた「工夫」
 リフレクション?
他の人が書いたクラスのメソッドを書き換える?
Unsafe?
メソッドが取り替えられないなら
インスタンスを取り替えてしまえ
ば
良いじゃない
以前の4人打ちオセロでの「工夫」
 最初に4人分戦わせて、一番強いひとが私の代わりに打てばよいのに。
 自 AI のコンストラクターで、事前に5回対戦して強いひと (AI) を選んどいて、
そいつを呼び出す。
class PlayerTab...
前回のオセロは機械学習 (Machine Learning)
5
コマンドライン ツール “ReversiGameRunner” を何日
もぶん回して、膨大のデータを生成
それを機械学習で解析して、最適なパラメーターを
ざわ…
ざわ…
今回のお題
Base64
エンコード/デコー
ド
スピード対決!!
7
1. 基本的な Base64 エンコード/デコード処理
2. 高速化の道
3. 「3バイト=4文字テーブル」への期待と挫折
4. IL への挑戦と挫折
5. そして、チートへ…
BuriKaigi2019 https://connpass....
基本的な
Base64 エンコード/デコード
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 8
10進 2進 文字 10進 2進 文字 10進 2進 文字 10進 2進 ...
9
0x3F, 0x25, 0x04, 0xE0
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
Base64 エンコード
0x3F 0x25 0x04 0xE0
0 0 ...
10
→ 0x3F, 0x25, 0x04, 0xE0
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
Base64 デコード
0x3F 0x25 0x04 0xE0
0 ...
11
要はビット演算を3バイト=4文字ごとに繰り返す
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
Base64 エンコード
12
ビット演算を4文字=3バイトごとに繰り返す
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
Base64 デコード
高速化の道
BuriKaigi2019 https://connpass.com/event/111062/
#BuriKaigi 13
14
LINQ
new
なるべくしない (できればしたくない)
できるだけ事前 (計測開始前) にしておく
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
遅いやつ
15
StringBuilder
Span<T> と Memory<T>
シンプルな1次元配列の方が早い
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
速いと噂のやつ
16
Buffer.BlockCopy(…) や Marshal.Copy(…)
コピーサイズが小さいときは、メソッド コールの
オーバーヘッドが割に合わない
BuriKaigi2019 https://connpass.com/event/...
17
マルチコアで並列処理
× AsParallel() 遅い
△ Parallel.For(…) まあまあ遅い
オーバーヘッドが大きすぎ
BuriKaigi2019 https://connpass.com/event/111062/ #B...
18
stacalloc
スタック領域だから早いのでは
Span<T> と組み合わせれば unsafe でなくても使える
今回は、毎回 allocate がどうしても必要なのは、最後の
return new string(...); な...
19
unsafe
ポインター
コピー時の境界チェックなし
まとめて転送可
文字列の中を直接書き替えられる
試したが、まあとにかく速い
今回は unsafe オプションなしのプロジェクトなので unsafe
はコンパイルできない
...
20
メソッド呼ばない (インラインにする)
メモリーのキャッシュのヒット率を意識する
なるべく近くのメモリーを使う
遠くを使うと、キャッシュのヒット率が著しく落
ちる
配列での境界チェックの排除
BuriKaigi2019 http...
21
答え: 1 と 2。 3は境界チェックが入る。
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
問題: 速いのはどれでしょう
ボトルネックの調査
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
22
string を new するボト
ルネックが消せない!
unsafe コードにして、ポイン
ター...
「3バイト=4文字テーブル」へ
の期待と挫折
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 23
この写真 の作成者 不明な作成者 は CC BY-SA のライセンスを許...
24
「3バイトが4文字に対応」の繰り返し
ならば、あらかじめ (計測前に) エンコード用と
デコード用の対応テーブルを作っておいて、
引けば良いのでは
エンコード用: 3bytes → 4characters テーブル
デコード用 :...
25
 なんなら、テーブルをC#のコードにして、埋め込んでも良い
かも
 配列の中身をC#のコードに変換するツールを作ってみた
1行 320 MBのC#
コンパイルが終わらない
BuriKaigi2019 https://connpas...
26
大きなヒープ領域のあちこちに
アクセスするため、キャッシュの
ヒット率が著しく落ちる
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
「3バイト=4文字テーブル」の...
IL への挑戦
と挫折
BuriKaigi2019 https://connpass.com/event/111062/
#BuriKaigi 27
28
事前コンパイル済み unsafe コードの IL を
動かしたら?
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
あきらめきれない unsafe への思い
uns...
29
IL を食わせるとこんな感じの C# ができるツール
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
IL → C# ツールの作成
IL_0000: nop
IL_...
30
unsafe な IL を書くのは大変
ポインターの扱いが大変
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
unsafe な IL
そして、
チートへ…
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 31
32
おや? 何故かこんなコードが…
BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi
#if CHEAT
 事前にタスクを乱立させといて、全CPUの使用率を100%に
...
33
 System.Runtime.CompilerServices.Unsafe.dll を、
事前に勝手に石野さんのマシンにダウンロードしてきて使う
とか
 unsafe でコンパイル済みの DLL を、ソースコードに
バイト列に埋め...
34
 失敗談しかない気もするけど、気のせい
 ちょっと新人プログラマーには見せられないソースコードに
 C#に詳しくなった
 C とアセンブリ言語 が恋しくなった
BuriKaigi2019 https://connpass.com/...
Upcoming SlideShare
Loading in …5
×

BuriKaigi2019 「C# ドキドキ・ライブコーディング」 小島の分

BuriKaigi2019 (2019/01/26)
https://connpass.com/event/111062/
「C# ドキドキ・ライブコーディング」

Related Books

Free with a 30 day trial from Scribd

See all
  • Be the first to comment

BuriKaigi2019 「C# ドキドキ・ライブコーディング」 小島の分

  1. 1. C# ドキドキ・ライブコーディング ~ 小島の分 ~ BuriKaigi2019 – 富山合同勉強会 2019/01/26 小島 富治雄 #burikaigi
  2. 2. 自己紹介  小島 富治雄  @Fujiwo  福井コンピュータアーキテクト株式会社  Microsoft MVP (2005-2019) C#関連
  3. 3. これまでの 対戦 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 2 この写真 の作成者 不明な作成者 は CC BY-SA のライセンスを許諾されています
  4. 4. 2015年のお題「七ならべ」のときに 思いついた「工夫」  リフレクション? 他の人が書いたクラスのメソッドを書き換える? Unsafe? メソッドが取り替えられないなら インスタンスを取り替えてしまえ ば 良いじゃない
  5. 5. 以前の4人打ちオセロでの「工夫」  最初に4人分戦わせて、一番強いひとが私の代わりに打てばよいのに。  自 AI のコンストラクターで、事前に5回対戦して強いひと (AI) を選んどいて、 そいつを呼び出す。 class PlayerTable : IEnumerable<KeyValuePair<Board.Piece, IPlayer>> { Dictionary<Board.Piece, IPlayer> playerDictionary = new Dictionary<Board.Piece, IPlayer>(); …… } class GameRunner { …… }
  6. 6. 前回のオセロは機械学習 (Machine Learning) 5 コマンドライン ツール “ReversiGameRunner” を何日 もぶん回して、膨大のデータを生成 それを機械学習で解析して、最適なパラメーターを ざわ… ざわ…
  7. 7. 今回のお題 Base64 エンコード/デコー ド スピード対決!!
  8. 8. 7 1. 基本的な Base64 エンコード/デコード処理 2. 高速化の道 3. 「3バイト=4文字テーブル」への期待と挫折 4. IL への挑戦と挫折 5. そして、チートへ… BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 今回の工夫 (謎) の数々
  9. 9. 基本的な Base64 エンコード/デコード BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 8 10進 2進 文字 10進 2進 文字 10進 2進 文字 10進 2進 文字 0 000000 A 16 010000 Q 32 100000 g 48 110000 w 1 000001 B 17 010001 R 33 100001 h 49 110001 x 2 000010 C 18 010010 S 34 100010 i 50 110010 y 3 000011 D 19 010011 T 35 100011 j 51 110011 z 4 000100 E 20 010100 U 36 100100 k 52 110100 0 5 000101 F 21 010101 V 37 100101 l 53 110101 1 6 000110 G 22 010110 W 38 100110 m 54 110110 2 7 000111 H 23 010111 X 39 100111 n 55 110111 3 8 001000 I 24 011000 Y 40 101000 o 56 111000 4 9 001001 J 25 011001 Z 41 101001 p 57 111001 5 10 001010 K 26 011010 a 42 101010 q 58 111010 6 11 001011 L 27 011011 b 43 101011 r 59 111011 7 12 001100 M 28 011100 c 44 101100 s 60 111100 8 13 001101 N 29 011101 d 45 101101 t 61 111101 9 14 001110 O 30 011110 e 46 101110 u 62 111110 + 15 001111 P 31 011111 f 47 101111 v 63 111111 /
  10. 10. 9 0x3F, 0x25, 0x04, 0xE0 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi Base64 エンコード 0x3F 0x25 0x04 0xE0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 15 54 20 2 57 0 ‘P’ ‘2’ ‘U’ ‘C’ ‘5’ ‘A’ ‘=’ ‘=’ 繰り返す → “P2UC5A==” 3バイト=4文字ごと 文字数は4の倍数 6ビットごと (足りないビットは0を追加) (足りない分は ‘=’) 対応する文字に変換 バイト列
  11. 11. 10 → 0x3F, 0x25, 0x04, 0xE0 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi Base64 デコード 0x3F 0x25 0x04 0xE0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 15 54 20 2 57 0 ‘P’ ‘2’ ‘U’ ‘C’ ‘5’ ‘A’ ‘=’ ‘=’ 繰り返す “P2UC5A==” 4文字=3バイト ごと 8ビットごと (余ったビットは不要) (末尾の‘=’は不要)対応する数値に変換 バイト列
  12. 12. 11 要はビット演算を3バイト=4文字ごとに繰り返す BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi Base64 エンコード
  13. 13. 12 ビット演算を4文字=3バイトごとに繰り返す BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi Base64 デコード
  14. 14. 高速化の道 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 13
  15. 15. 14 LINQ new なるべくしない (できればしたくない) できるだけ事前 (計測開始前) にしておく BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 遅いやつ
  16. 16. 15 StringBuilder Span<T> と Memory<T> シンプルな1次元配列の方が早い BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 速いと噂のやつ
  17. 17. 16 Buffer.BlockCopy(…) や Marshal.Copy(…) コピーサイズが小さいときは、メソッド コールの オーバーヘッドが割に合わない BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 速いと噂のやつ
  18. 18. 17 マルチコアで並列処理 × AsParallel() 遅い △ Parallel.For(…) まあまあ遅い オーバーヘッドが大きすぎ BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 速いと噂のやつ
  19. 19. 18 stacalloc スタック領域だから早いのでは Span<T> と組み合わせれば unsafe でなくても使える 今回は、毎回 allocate がどうしても必要なのは、最後の return new string(...); なので、使えない BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 速いと噂のやつ
  20. 20. 19 unsafe ポインター コピー時の境界チェックなし まとめて転送可 文字列の中を直接書き替えられる 試したが、まあとにかく速い 今回は unsafe オプションなしのプロジェクトなので unsafe はコンパイルできない BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 本当に速いやつ
  21. 21. 20 メソッド呼ばない (インラインにする) メモリーのキャッシュのヒット率を意識する なるべく近くのメモリーを使う 遠くを使うと、キャッシュのヒット率が著しく落 ちる 配列での境界チェックの排除 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi その他
  22. 22. 21 答え: 1 と 2。 3は境界チェックが入る。 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 問題: 速いのはどれでしょう
  23. 23. ボトルネックの調査 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 22 string を new するボト ルネックが消せない! unsafe コードにして、ポイン ターを使えば、解決するが…
  24. 24. 「3バイト=4文字テーブル」へ の期待と挫折 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 23 この写真 の作成者 不明な作成者 は CC BY-SA のライセンスを許諾されています
  25. 25. 24 「3バイトが4文字に対応」の繰り返し ならば、あらかじめ (計測前に) エンコード用と デコード用の対応テーブルを作っておいて、 引けば良いのでは エンコード用: 3bytes → 4characters テーブル デコード用 : 4characters → 3bytes テーブル Dictionary<T> や Hashtable は遅いので、 一次元配列で BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 「3バイト=4文字テーブル」
  26. 26. 25  なんなら、テーブルをC#のコードにして、埋め込んでも良い かも  配列の中身をC#のコードに変換するツールを作ってみた 1行 320 MBのC# コンパイルが終わらない BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 「3バイト=4文字テーブル」
  27. 27. 26 大きなヒープ領域のあちこちに アクセスするため、キャッシュの ヒット率が著しく落ちる BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 「3バイト=4文字テーブル」のボトルネッ ク
  28. 28. IL への挑戦 と挫折 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 27
  29. 29. 28 事前コンパイル済み unsafe コードの IL を 動かしたら? BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi あきらめきれない unsafe への思い unsafe をコンパイルできないのなら、 コンパイルしなければ良いじゃない
  30. 30. 29 IL を食わせるとこんな感じの C# ができるツール BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi IL → C# ツールの作成 IL_0000: nop IL_0001: nop IL_0002: ldarg.1 IL_0003: dup IL_0004: stloc.1 IL_0005: brfalse.s IL_000C IL_0007: ldloc.1 IL_0008: ldlen IL_0009: conv.i4 IL_000A: brtrue.s IL_0011 IL_000C: ldc.i4.0 IL_000D: conv.u …
  31. 31. 30 unsafe な IL を書くのは大変 ポインターの扱いが大変 BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi unsafe な IL
  32. 32. そして、 チートへ… BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 31
  33. 33. 32 おや? 何故かこんなコードが… BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi #if CHEAT  事前にタスクを乱立させといて、全CPUの使用率を100%に  自分の番のときだけ、CPU負荷を下げる
  34. 34. 33  System.Runtime.CompilerServices.Unsafe.dll を、 事前に勝手に石野さんのマシンにダウンロードしてきて使う とか  unsafe でコンパイル済みの DLL を、ソースコードに バイト列に埋め込んどいて、事前に書き出して、動的に ロードして使うとか BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi その他のCHEAT やりすぎ → こういうのは、もはや室星さんの役割
  35. 35. 34  失敗談しかない気もするけど、気のせい  ちょっと新人プログラマーには見せられないソースコードに  C#に詳しくなった  C とアセンブリ言語 が恋しくなった BuriKaigi2019 https://connpass.com/event/111062/ #BuriKaigi 最後に感想

×