4
6

初めてのGPU CUDAプログラミング

Last updated at Posted at 2024-07-22
ショートストーリー: 「初めてのGPU CUDAプログラミング」

陽介はコンピュータサイエンスを専攻する大学生で、卒業研究のテーマとしてGPUプログラミングに挑戦することを決めた。彼はこれまでCPUを使ったプログラミングには慣れていたが、GPUについては全くの初心者だった。卒業研究の初日に、彼の指導教官である田中教授は、簡単な課題を出した。

「陽介、今日は初めてのGPUプログラミングの課題として、配列の各要素を2倍にするプログラムを作ってみてくれ。PythonとPyCUDAを使って、これをGoogle Colab上で実行するんだ。」

陽介は教授の指示に従い、まずPyCUDAの使い方を調べ始めた。Google Colabにアクセスし、PyCUDAのインストールから始めた。彼の目の前の画面には、PyCUDAのインストールコマンドが入力されていた。


# PyCUDAのインストール
!pip install pycuda

次に、陽介は教授が指定した通りに、CUDAカーネルをPythonコードに書き込み始めた。彼はまだ少し緊張していたが、一つ一つのステップを確実に進めた。


import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import numpy as np

# CUDAカーネル
kernel_code = """
__global__ void doubleElements(int *d_array, int size) {
    int index = threadIdx.x + blockIdx.x * blockDim.x;
    if (index < size) {
        d_array[index] *= 2;
    }
}
"""

# カーネルをコンパイル
mod = SourceModule(kernel_code)
double_elements = mod.get_function("doubleElements")

# ホスト側のデータ
h_array = np.array([1, 2, 3, 4, 5], dtype=np.int32)

# デバイス側のデータ
d_array = cuda.mem_alloc(h_array.nbytes)
cuda.memcpy_htod(d_array, h_array)

# カーネルの起動
block_size = 256
grid_size = (h_array.size + block_size - 1) // block_size
double_elements(d_array, np.int32(h_array.size), block=(block_size, 1, 1), grid=(grid_size, 1, 1))

# 結果をホスト側にコピー
cuda.memcpy_dtoh(h_array, d_array)

# 結果を表示
print("Result:", h_array)

プログラムを書き終えた陽介は、緊張しながら実行ボタンを押した。コンソールに表示されるインストールと実行のメッセージを見つめながら、心臓が高鳴るのを感じていた。やがて、結果が表示された。

Result: [ 2 4 6 8 10]

陽介の顔に笑みが広がった。「やった、成功だ!」彼は声をあげた。自分が初めて書いたGPUプログラムが正しく動作したことに、達成感と満足感が湧き上がった。

その日、陽介はGPUプログラミングの楽しさとその力強さを初めて実感した。教授から出された簡単な課題であったが、それは彼にとって大きな一歩だった。これを機に、陽介はもっと高度なGPUプログラミングの世界に踏み出す決意を固めた。

PyCUDAはPythonからCUDAを呼び出すためのライブラリです。以下にPyCUDAを使って同様の配列の要素を2倍にする例を示します。

まず、Google ColabのノートブックでPyCUDAをインストールします。


!pip install pycuda


import pycuda.driver as cuda
import pycuda.autoinit
from pycuda.compiler import SourceModule
import numpy as np

# CUDAカーネル
kernel_code = """
__global__ void doubleElements(int *d_array, int size) {
    int index = threadIdx.x + blockIdx.x * blockDim.x;
    if (index < size) {
        d_array[index] *= 2;
    }
}
"""

# カーネルをコンパイル
mod = SourceModule(kernel_code)
double_elements = mod.get_function("doubleElements")

# ホスト側のデータ
h_array = np.array([1, 2, 3, 4, 5], dtype=np.int32)

# デバイス側のデータ
d_array = cuda.mem_alloc(h_array.nbytes)
cuda.memcpy_htod(d_array, h_array)

# カーネルの起動
block_size = 256
grid_size = (h_array.size + block_size - 1) // block_size
double_elements(d_array, np.int32(h_array.size), block=(block_size, 1, 1), grid=(grid_size, 1, 1))

# 結果をホスト側にコピー
cuda.memcpy_dtoh(h_array, d_array)

# 結果を表示
print("Result:", h_array)

説明
CUDAカーネルの定義: CUDAカーネル関数をPythonの文字列として定義します。
カーネルのコンパイル: SourceModuleを使ってカーネルコードをコンパイルし、カーネル関数を取得します。
ホスト側のデータ: NumPy配列としてホスト側のデータを準備します。
デバイス側のデータ: CUDAメモリを割り当て、ホスト側のデータをデバイス側にコピーします。
カーネルの起動: double_elements関数を呼び出してカーネルを起動します。
結果のコピー: 結果をデバイスからホストにコピーします。
結果の表示: 計算結果を表示します。
この方法により、Google Colab上でPyCUDAを使ってCUDAプログラムを実行することができます。

思ったより難しくなさそうですね。GPU CUDAプログラミング。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6