第1回 関東gpgpu勉強会 topcoder/nvidia主催cudaプログラミングコンテスト参加記
DESCRIPTION
TRANSCRIPT
TopCoder/NVIDIA 主催CUDA プログラミングコンテスト参加記
@foota2012 年 6 月 2 日
おまえ誰よ ? @foota / nox 並列処理のコードを書く IT 企業に勤務
並列処理・ GPGPU 機械学習
以前は某研究機関の研究員 分子動力学 (MD) 計算 創薬の研究
「良いもの。悪いもの。」 http://handasse.blogspot.com/
今日話すこと TopCoder とは CUDA Superhero Challenge 問題を読む 問題を考える 問題を解く まとめ
TopCoder とは 世界で最も規模の大きい競技プログラミングを
運営する組織 代表的なプログラミングコンテストとして、数
時間の短期間で問題を解く SRM と数週間の長期間で問題を解くマラソンマッチ (MM) がある
今日話す CUDA Superhero Challenge はGPGPU を利用したマラソンマッチ
最近ではデータマイニングなどの機械学習を利用した賞金付きマラソンマッチが多い
CUDA Superhero Challenge 2009 年 10 月に開催された、 TopCoder
と NVIDIA による CUDA の国際プログラミングコンテスト
賞金総額 $5,000 ! しかし、賞金圏内ぎりぎりの 5 位だった
ので $250 と金額はしょぼい…
海外のニュースサイトに載ったりする
問題を読む
何するの ? 連結成分ラベリングを GPU を使ってでき
るだけ高速に解くだけ 連結成分ラベリングって何 ?
連結成分ラベリング
連続した同じ領域 ( 色 ) ごとにラベル付けを行う。 閾値を設けて、隣り合うピクセルの色の差が閾値以下なら同じ
領域だとみなす。 | 赤 1- 赤 0| + | 緑 1- 緑 0| + | 青 1- 青 0| ≦ 閾値
連結度は 4 と 8 があり、 4 なら上下左右と結合していて、 8 ならそれに加えてななめの方向も結合している。
上記の画像を連結度 4 として考えた場合、水色、黄色、緑色、ピンク、青色、オレンジの 5 つの領域に分けられる。結合度 8の場合は 2 つの領域に分けられる。
条件 入力画像は、面積が 3 億ピクセル、一辺
の長さが 2 万ピクセルを最大とする 1 画像につき 1 分以内に計算しなければ
ならない 使用できるメモリは 2,500MB まで コンテストで使用される GPU デバイスは
Tesla C1060
入力画像 (1)0, 1
2, 3
4 5
6 7
8
9
10
入力画像 (2)11
12
13
14
15
16
入力画像 (3)
1817
計算データNo. 連結度 閾値 サイズ
0 4 0 64x64
1 8 30 64x64
2 4 25 100x300
3 8 0 100x300
4 8 0 1000x768
5 4 25 4000x4000
6 4 10 800x600
7 8 60 1316x1252
8 4 10 1502x1482
9 4 30 2145x1213
No. 連結度 閾値 サイズ10 8 60 987x735
11 4 30 1374x1040
12 4 10 1500x1131
13 8 60 4194x4194
14 8 60 6672x6340
15 4 30 900x900
16 8 60 6000x6000
17 4 10 16000x16000
18 8 30 14321x10000
コードの書き方
Definition
Class: CCL
Method: cuda_ccl
Parameters: vector<int>, int, int, int
Returns: vector<int>
Method signature:
vector<int> cuda_ccl(vector<int> image, int W, int degree_of_connectivity, int threshold)
実行環境 CPU: Intel Xeon X5650 @2.67GHz GPU: Tesla C2050
問題を考える ラベルの初期化として、左上から順番に番
号を付ける。 それぞれのピクセルで、その周りのピクセ
ルのラベルと比較して最も小さいラベルを新しいラベルする。
それを繰り返して、ラベルが更新されなくなったら終了。
GPGPU なら複数スレッドで一気にラベルを更新できるし速そうだ !
ラベルの初期化
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
1 1 2 3 4 5 7 7
9 9 10 4 5 6 14 8
9 10 11 12 13 14 15 16
17 18 19 27 21 22 23 31
25 26 27 28 36 30 31 32
33 34 35 44 44 38 39 40
41 50 50 44 45 54 54 55
49 50 59 59 60 54 55 56
1 1 1 2 3 4 7 7
9 9 9 3 4 5 6 7
9 9 10 4 5 6 14 8
9 17 18 19 13 14 15 23
17 18 19 27 28 22 23 31
25 26 27 44 38 30 31 32
33 50 44 44 44 54 54 54
41 50 59 59 54 54 54 55
1 1 1 1 2 3 7 7
9 9 9 2 3 4 5 7
9 9 9 3 4 5 6 7
9 9 10 18 5 6 14 15
9 17 18 19 27 14 15 23
17 18 19 38 30 22 23 31
25 44 44 44 38 54 54 54
33 50 59 54 54 54 54 54
1 1 1 1 1 2 7 7
9 9 9 1 2 3 4 7
9 9 9 2 3 4 5 7
9 9 9 10 4 5 6 14
9 9 10 18 19 6 14 15
9 17 18 30 22 14 15 23
17 44 44 38 30 54 54 54
25 44 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 2 3 7
9 9 9 1 2 3 4 7
9 9 9 9 3 4 5 6
9 9 9 10 18 5 6 14
9 9 10 22 14 6 14 15
9 44 38 30 22 54 54 54
17 44 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 2 7
9 9 9 1 1 2 3 7
9 9 9 9 2 3 4 5
9 9 9 9 10 4 5 6
9 9 9 14 6 5 6 14
9 38 30 22 14 54 54 54
9 44 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 2 7
9 9 9 9 1 2 3 4
9 9 9 9 9 3 4 5
9 9 9 6 5 4 5 6
9 30 22 14 6 54 54 54
9 38 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 2 3
9 9 9 9 9 2 3 4
9 9 9 5 4 3 4 5
9 22 14 6 5 54 54 54
9 30 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 2
9 9 9 9 9 1 2 3
9 9 9 4 3 2 3 4
9 14 6 5 4 54 54 54
9 22 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 2
9 9 9 3 2 1 2 3
9 6 5 4 3 54 54 54
9 14 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 2 1 1 1 2
9 5 4 3 2 54 54 54
9 6 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 4 3 2 1 54 54 54
9 5 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 3 2 1 1 54 54 54
9 4 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 2 1 1 1 54 54 54
9 3 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 1 1 1 1 54 54 54
9 2 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 1 1 1 1 54 54 54
9 1 54 54 54 54 54 54
隣接伝播
隣接伝播 結果 (1)
No.連結度 閾値 サイズ CPU GPU 倍率
0 4 0 64x64 0.012176 0.110757 0.110
1 8 30 64x64 0.010722 0.114190 0.094
2 4 25 100x300 0.596673 0.170903 3.491
3 8 0 100x300 0.348009 0.115680 3.008
4 8 0 1000x768 9.350450 0.379094 24.665
5 4 25 4000x4000 237.985000 15.749900 15.110
6 4 10 800x600 5.883900 0.323574 18.184
7 8 60 1316x1252 0.284824 1.326350 0.215
8 4 10 1502x1482 32.217800 1.473260 21.868
9 4 30 2145x1213 1.219730 3.723310 0.328
隣接伝播 結果 (2)
No.連結度 閾値 サイズ CPU GPU 倍率
10 8 60 987x735 0.062973 0.488163 0.129
11 4 30 1374x1040 8.120030 1.567890 5.179
12 4 10 1500x1131 16.570400 0.507686 32.639
13 8 60 4194x4194 1111.440000 27.248900 40.788
14 8 60 6672x6340 1199.790000 101.794000 11.786
15 4 30 900x900 0.322443 0.755994 0.427
16 8 60 6000x6000 35.604300 65.525000 0.543
17 4 10 16000x16000
5723.870000 2472.830000
2.315
18 8 30 14321x10000
425661.000000
10855.60000
39.211
さらに問題を考える もっと速くできないか ? ピクセル一つずつ確認していくのは効率
が悪い気がする。 一列すべてを処理してしまってはどうだろ
うか。 4 方向もしくは 8 方向を順に調べよう !
指向的伝播ラベリング
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
1 2 3 4 5 6 7 8
9 10 11 4 5 6 15 8
9 10 11 4 5 6 15 8
9 10 11 28 5 6 15 32
9 10 11 28 37 6 15 32
9 10 11 44 45 6 15 32
9 50 51 44 45 54 55 56
9 50 59 60 61 54 55 56
1 1 1 1 1 1 7 7
9 9 9 4 4 4 4 8
9 9 9 4 4 4 4 8
9 9 9 9 5 5 5 5
9 9 9 9 9 6 6 6
9 9 9 44 44 6 6 6
9 50 50 44 44 54 54 54
9 50 59 59 59 54 54 54
1 1 1 1 1 1 7 7
9 9 9 4 4 4 4 8
9 9 9 4 4 4 4 8
9 9 9 9 5 5 5 5
9 9 9 9 9 6 6 6
9 9 9 44 44 6 6 6
9 50 50 44 44 54 54 54
9 50 59 59 59 54 54 54
1 1 1 1 1 1 7 7
9 9 9 4 4 4 4 8
9 9 9 4 4 4 4 8
9 9 9 9 5 5 5 5
9 9 9 9 9 6 6 6
9 9 9 6 6 6 6 6
9 44 44 44 44 54 54 54
9 50 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 4 7
9 9 9 1 1 1 4 7
9 9 9 9 1 1 4 5
9 9 9 9 9 1 4 5
9 9 9 6 6 1 4 5
9 44 44 6 6 54 54 54
9 44 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 6 6 1 1 1
9 44 44 6 6 54 54 54
9 44 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 6 6 1 1 1
9 44 44 6 6 54 54 54
9 44 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 6 6 6 6 54 54 54
9 44 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 6 6 1 1 54 54 54
9 6 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 6 6 1 1 54 54 54
9 6 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 6 6 1 1 54 54 54
9 6 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 1 1 1 1 54 54 54
9 6 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 1 1 1 1 54 54 54
9 1 54 54 54 54 54 54
指向的伝播ラベリング 結果 (1)
No.連結度 閾値 サイズ CPU GPU 倍率
0 4 0 64x64 0.002382 0.106349 0.022
1 8 30 64x64 0.010193 0.105844 0.096
2 4 25 100x300 0.096171 0.236392 0.407
3 8 0 100x300 0.032573 0.135166 0.241
4 8 0 1000x768 3.502950 0.981031 3.571
5 4 25 4000x4000 124.643000 6.453890 19.313
6 4 10 800x600 0.319645 0.213199 1.499
7 8 60 1316x1252 0.774412 0.277574 2.790
8 4 10 1502x1482 15.520500 3.608650 4.301
9 4 30 2145x1213 0.970901 0.342785 2.832
指向的伝播ラベリング 結果 (2)
No.連結度 閾値 サイズ CPU GPU 倍率
10 8 60 987x735 0.153554 0.144784 1.061
11 4 30 1374x1040 3.325760 0.696785 4.773
12 4 10 1500x1131 7.125450 1.447230 4.924
13 8 60 4194x4194 31.172800 2.270510 13.729
14 8 60 6672x6340 3728.890000 218.461000 17.069
15 4 30 900x900 0.138539 0.138232 1.002
16 8 60 6000x6000 52.699100 3.995920 13.188
17 4 10 16000x16000
7510.120000 403.630000 18.606
18 8 30 14321x10000
6392.590000 343.640000 18.603
さらにもっと問題を考える さらにもっと速くできないか ? あるピクセルの周りに小さいラベルを持つピクセ
ルがあり、そのピクセルの周りにはもっと小さいラベルを持つピクセルがあり、さらにその先にはもっともっと小さいラベルを持つピクセルが…というようにラベルをたどって行けるんじゃね ?
周りのラベルを調べる走査フェーズ、一番小さいラベルをたどる解析フェーズ、ラベルを付け直すラベル付けフェーズの 3 つのフェーズで構成する。
ラベル等価
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
1 21 32 43 54 65 7 87
9 109 111
0 124 135 146 151
4 168
179 181
0
191
1
201
2
211
3
221
4
231
5
241
6
251
7
261
8
271
9
282
7
292
1
302
2
312
3
323
1
332
5
342
6
352
7
362
8
373
6
383
0
393
1
403
2
413
3
423
4
433
5 44 454
4
463
8
473
9
484
0
494
1 50 515
0
524
4
534
5 54 555
4
565
5
574
9
585
0 59 605
9
616
0
625
4
635
5
645
6
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 44 441 1 1 1
9 50 504
4 44 44 54 54 54
9 50 59 59 595
4 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 441 1 1 1 1
9 504
4 44 441 441 54 54 54
9 50 59 595
4 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 44 441 1 1 54 54 54
9 504
4
595
4 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 441 1 1 1 54 54 54
9 44 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 1 1 1 1 54 54 54
9 441 54 54 54 54 54 54
1 1 1 1 1 1 7 7
9 9 9 1 1 1 1 7
9 9 9 1 1 1 1 7
9 9 9 9 1 1 1 1
9 9 9 9 9 1 1 1
9 9 9 1 1 1 1 1
9 1 1 1 1 54 54 54
9 1 54 54 54 54 54 54
ラベル等価 結果 (1)
No.連結度 閾値 サイズ CPU GPU 倍率
0 4 0 64x64 0.000890 0.102171 0.009
1 8 30 64x64 0.004953 0.099847 0.050
2 4 25 100x300 0.006969 0.101593 0.069
3 8 0 100x300 0.006359 0.100254 0.063
4 8 0 1000x768 0.159436 0.107507 1.483
5 4 25 4000x4000 1.968550 0.200410 9.823
6 4 10 800x600 0.075281 0.103099 0.730
7 8 60 1316x1252 0.231614 0.118273 1.958
8 4 10 1502x1482 0.502064 0.119762 4.192
9 4 30 2145x1213 0.273070 0.121070 2.255
ラベル等価 結果 (2)
No.連結度 閾値 サイズ CPU GPU 倍率
10 8 60 987x735 0.068256 0.109083 0.626
11 4 30 1374x1040 0.315708 0.111239 2.838
12 4 10 1500x1131 0.430731 0.116800 3.688
13 8 60 4194x4194 3.432670 0.215678 15.916
14 8 60 6672x6340 14.829300 0.424460 34.937
15 4 30 900x900 0.082415 0.107684 0.765
16 8 60 6000x6000 8.459500 0.363360 23.281
17 4 10 16000x16000
50.543600 0.276371 182.883
18 8 30 14321x10000
50.221500 1.696280 29.607
どれだけ速くなったのか ? No.13 の解像度 4,194×4,194
の画像で比較してみる。 隣接伝播の CPU では 1,111秒
の実行時間が掛かっていたが、ラベル等価の GPU では 0.21秒になった。 5,000倍以上の高速化を実現 !
GPU 同士の比較では 126倍の差が出た。 No.18 では隣接伝播の CPU とラベル等価
の GPU で 25 万倍以上の差がついた !
まとめアルゴリズムが重要。その上で GPGPU に
よる高速化を行えば、素晴らしい成果を期待できる。
アルゴリズムを深く考える訓練として、 TopCoder のマラソンマッチはおすすめ !
最近では 1 万ドルほどの賞金付きマラソンマッチが多いので小遣い稼ぎになるかも ?
コード & 参考文献 Github
https://github.com/foota/ccl References
K. Hawick, A. Leist and D. Playne, Parallel graph component labelling with GPUs and CUDA, Parallel Computing 36 (12) 655-678 (2010)
O. Kalentev, A. Rai, S. Kemnitz and R. Schneider, Connected component labeling on a 2D grid using CUDA, J. Parallel Distrib. Comput. 71 (4) 615-620 (2011)
V. M. A. Oliveira and R. A. Lotufo, A study on connected components labeling algorithms using GPUs, SIBGRAPI (2010)
ご清聴ありがとうございました !