複数のデバイスにおける CUDALink

Wolfram言語の中核である関数型,およびリスト志向の特性により,CUDALink は組込みの即時データ並列化が提供でき,利用できるGPUカードに自動的に計算を分配する.

はじめに

まず CUDALink アプリケーションをロードする.

デバイス数と同じだけワーカーカーネルを開始する.

$CUDADeviceCountはシステム上のデバイス数である.

$CUDADeviceCountシステム上のCUDAデバイス数

$CUDADeviceCountはシステム上のCUDA GPUデバイス数を取得する

CUDALink を全ワーカーカーネル上にロードする.

CUDALink は既存のWolfram言語並列計算機能を使って複数のGPU上で実行する.このセクションでは,以下の関数を使う.

ParallelNeedsパッケージを全並列サブカーネルにロードする
DistributeDefinitions並列計算に必要な定義を分配する
ParallelEvaluate利用できる全並列カーネルで入力式を評価して得られた結果のリストを返す

CUDALink はWolfram言語の並列計算機能で複数のGPUを使う

すべてのカーネル上の$CUDADevice変数を設定する.

CUDALink 関数

画像処理,線形代数,高速フーリエ(Fourier)変換等の高レベル CUDALink 関数は他のWolfram言語関数と同様に異なるカーネルで使用できる.違いは,$CUDADeviceが計算が行われるデバイスに設定されるということだけである.

画像の名前をExampleDataTestImagesデータ集合から取られるように設定する.

変数imgNamesをワーカーカーネルに分配する.

ExampleDataから取られた画像にCUDAErosionを適用する.

速度が2倍改善されたことに注目されたい.これらの画像は小さく,データは転送されなければならないので,パフォーマンスは4倍は上がらない.

その他の場合は,データの転送にかかる時間は計算に必要な時間に比べると多くない.ここでは2000のランダムな整数ベクトルを割り当てる.

各デバイスにCUDAFoldをマップする.

より速度が上がった.

CUDALink プログラミング

CUDAFunctionは最適化されており,GPUに局所的であるため,DistributeDefinitionsを使ってワーカーカーネルと共有することはできない.このセクションではGPUをプログラムする別の方法を述べる.

2を足す

ベクトルに2を足す基本的なCUDAコードをロードする.

CUDAFunctionをロードする.割当てにSetDelayedが使われている.これにより,DistributeDefinitionsCUDAFunctionLoad呼出しのすべての従属変数を分配することができる.

入力パラメータを設定する.

ワーカーカーネル間に定義を分配する.

異なるCUDAデバイスを使って各ワーカーカーネルでCUDAFunctionを実行する.

最初の20要素を示す結果を集める.

マンデルブロ(Mandelbrot)集合

これは CUDALink ドキュメントの別のセクションで定義されたものと同じCUDAコードである.

CUDAFunctionをロードする.

ワーカーカーネルと変数を共有する.

それぞれ異なるズームレベルでカーネルを開始し,"Bit"画像を返す.

乱数生成器

以下のファイルにメルセンヌツイスタ(Mersenne Twister)が実装されている.

関数をWolfram言語にロードする.

CUDAFunctionのための入力変数を設定する.

mersenneTwister関数と入力パラメータをを分配する.

シードの値を割り当てる.乱数が相関性を持たないようにするために,シードの評価は各ワーカーカーネルで行われなければならないことに注意.出力メモリも割り当てられ,計算が行われ,結果が可視化される.

メモリ

CUDAMemoryはカーネルとそれがロードされているデバイスの両方に結び付けられているため,ワーカーカーネルには分配できない.

マスターカーネルにメモリをロードする.

それから定義を分配する.

分配されたCUDAMemoryはワーカーカーネルによって操作することはできない.

メモリはParallelEvaluateを使ってワーカーカーネルにロードできる.

ParallelEvaluateを使ってメモリ上でさらに処理を行う.

帯域幅

場合によっては,データの転送に費やす時間が計算に必要な時間より多くなることがある.

大きなリストをロードする.

並列処理では大きなリストをワーカーカーネルと共有しなければならないので,直列処理を行う場合より大幅に時間がかかる.

データを転送する必要がない直列処理の方が速い.