カーネルとは、1つのスレッドがする仕事を書いた関数
カーネルとは、GPUの1つのスレッドがする仕事を書いた関数です。起動すると、全部のスレッドが同じカーネルを、それぞれ自分の要素に走らせます。
このレッスンでは、2つの配列を足すカーネルを、Pythonで書いて動かします。ラボにGPUはなく、起動はPythonのループで真似ます。
このレッスンのゴール
メモ
自分の番号を求め、範囲を確かめて計算するカーネルを書いて、起動を真似られる。
重要な言葉
| ことば | いみ | れい |
|---|---|---|
| カーネル | 1つのスレッドがする仕事を書いた関数 | |
| 起動 | 全スレッドにカーネルを走らせること | |
| 範囲の確認 | 自分の番号が、データの中かを確かめること | if i < n |
| ブロックの数 | 要素を覆うのに必要な、ブロックの個数 | |
| 何もしないスレッド | 範囲の外にいて、仕事をしないスレッド |
学生が入力するセルは、このプレビューでは空白です。
カーネルは、自分の番号を求めて仕事をする
カーネルの中身は3つの手順です。自分の通し番号 i を求めます。i がデータの中かを確かめます。中なら、i番目だけを計算します。
全スレッドが同じ手順を走らせるので、ループは要りません。ループに当たる部分を、起動が受け持ちます。
7個を、ブロックの大きさ3で処理する
| ブロック | スレッドの番号 | 通し番号 | すること |
|---|---|---|---|
| 0 | 0, 1, 2 | 0, 1, 2 | 全員が計算する |
| 1 | 0, 1, 2 | 3, 4, 5 | 全員が計算する |
| 2 | 0, 1, 2 | 6, 7, 8 | 6だけ計算し、7と8は何もしない |
学生が入力するセルは、このプレビューでは空白です。
カーネルと起動をPythonで真似る
# カーネルは、1つのスレッドがする仕事です。起動は、全スレッドにそれを走らせます。
prices = [120, 300, 80, 450, 60, 90, 200]
shipping = [50, 50, 50, 50, 50, 50, 50]
n = len(prices)
result = [0] * n
block_dim = 3
grid_dim = (n + block_dim - 1) // block_dim
def kernel(block_idx, thread_idx):
i = block_idx * block_dim + thread_idx
if i < n:
result[i] = prices[i] + shipping[i]
return 1
return 0
worked = 0
for block_idx in range(grid_dim):
for thread_idx in range(block_dim):
worked = worked + kernel(block_idx, thread_idx)
print("ブロック数:", grid_dim, "仕事をしたスレッド:", worked)
print(result)
# prices に値段を2つ足して、ブロック数がどう変わるか見ましょう。
範囲の確認を忘れると、データの外を触る
要素の数がブロックの大きさの倍数でないと、スレッドが余ります。余ったスレッドの番号は、データの長さ以上です。
確認なしに計算すると、存在しない場所を読み書きします。だからカーネルの最初に、番号がデータの中かを確かめます。
よくある間違い
注意
スレッドの数は、要素の数にぴったり合わせられると思いがちです。ブロックの大きさが決まっていると、余りが出ます。ブロックの数は切り上げ、余ったスレッドには範囲の確認で何もさせません。
ラボの端末で、カーネルのコードを読む
ラボにGPUはありません。ラボのスクリプトも、同じカーネルをPythonで真似ています。下の Run は、そのコードを表示するだけです。
コードの中の def kernel が、カーネルです。ブロックの番号とスレッドの番号を受け取り、block_idx * block_dim + thread_idx で自分の番号を求めます。
スクリプトのコードを読む
docker exec jupyter cat steps/kernel.pyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
カーネルの行を探す
docker exec jupyter grep -n "def kernel" steps/kernel.pyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
さらに挑戦: 多すぎるスレッド
1000個の要素に、ブロックの大きさ256で起動すると、ブロックは4つ、スレッドは1024個です。
何もしないスレッドは、24個です。要素が1025個になると、ブロックの数はどうなるでしょうか。自分の言葉で説明しましょう。