詳しくは「表:clEnqueueNDRangeKernel」(Table B.88, “表:clEnqueueNDRangeKernel”)を参照ください。
pyopencl.enqueue_nd_range_kernel( queue, #(1) kernel, #(2) global_work_size, #(3) local_work_size, #(4) global_work_offset=None, #(5) wait_for=None, #(6) g_times_l=False) #(7)
有効なコマンドキューを指定。 | |
有効なカーネルオブジェクトを指定。 | |
要素数work_dimの配列で、カーネル関数を実行するwork_dim次元のグローバルワークアイテムの個数を指定。 | |
要素数work_dimの配列で、カーネル関数を実行する各ワークグループを構成するワークアイテムの数(ワークグループのサイズとも呼ぶ)を指定。 | |
要素数work_dimの配列でワークアイテムのグローバルIDを決定する際のオフセット値を指定。 | |
このコマンドが実行される前に完了されているイベントを指定 | |
global_work_sizeをlocal_work_sizeで乗じた値を使います。 |
enqueue_nd_range_kernel関数を実装する際に一番判断に迷うのは、以下の3つの引数です。
オフセットは作業したいデータの位置や、アルゴリズムの設計により恣意的に開発者が決めるものですが、原則として(0,0,0)で支障はないかと思います。
グローバルワークサイズ引数についても同様ですが、一般にワークサイズは2の冪乗としてください。これはプロセッサの演算ユニットをなるべき多く使うための最も基本的な処方箋です。プロセッサを有効に使うためには、できるだけ多くのグローバルワークサイズ引数があったほうが良いです。
ローカルワークサイズ引数は、IntelのGPUであれば64〜128個とします。ローカルワークサイズを決定する際に覚えておきたい点は、ローカルワークサイズは、ワークグループ数を決めるということです。
例えば1024個のグローバルワークサイズに対して、128個のワークグループ数を考えてみましょう。この場合のワークグループ数は8個(1024/128)となります。しかしローカルワークサイズが大きいと、共有ローカルメモリのサイズが肥大化して、推奨されるメモリ使用量の閾値(Intelは4K)を超える可能性が高くなります。
詳細は 「ワークグループ数とワークグループサイズの最適化」(Table 13.15, “ワークグループ数とワークグループサイズの最適化”) を参照ください。
clSample.py.
import pyopencl as cl import numpy as np data = np.arange(16).astype(np.int32) ctx = cl.Context([cl.get_platforms()[0].get_devices()[0]]) queue = cl.CommandQueue(ctx) mf = cl.mem_flags data_mem = cl.Buffer(ctx, mf.USE_HOST_PTR, hostbuf=data) program = cl.Program(ctx, """ __kernel void square(__global int* data) { size_t gid = get_global_id(0); data[gid] *= data[gid]; } """).build() program.square(queue, (16,), (4,), data_mem) # program.square(queue, np.array([16,1,1]), np.array([1,1,1]) None) cl.enqueue_copy(queue, data, data_mem) print(data)
出力.
[0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225]
詳しくは「表:clEnqueueTask」(Table B.89, “表:clEnqueueTask”)、(タスク並列プログラミング)を参照ください。
enqueue_taskはenqueue_nd_range_kernel関数がデータ並列プログラミングを指すのと対比して、異なるタスクを並列で処理させるために使うことができます。
通常のマルチスレッドプログラミングのOpenCLバージョンと考えて頂くと分かりやすいかと思います。
pyopencl.enqueue_task( queue, #(1) kernel, #(2) wait_for=None) #(3)
Copyright 2018-2019, by Masaki Komatsu