私はCUDAの初心者です。
これまでのところ、各SMには(スレッドの)8つのブロックがあることを学びました。配列内の要素に2を掛けるという単純な仕事があるとしましょう。ただし、データはスレッドよりも少なくなっています。
スレッドの「テール」を切り取ってアイドル状態にすることができたので、問題ありません。しかし、私が正しく理解していれば、これは、一部のSMが100%の作業を取得し、一部の部分(またはまったく機能しない)を取得することを意味します。
そこで、どのSMが特定のスレッドで実行されているかを計算し、各SMが同じ量の作業を行うように計算したいと思います。
そもそもそれが理にかなっていることを願っています:-)もしそうなら、どのSMが与えられたスレッドを実行しているかを計算する方法は?または-現在のSMのインデックスとそれらの総数?言い換えれば、SM用語でthreadDim/threadIdxと同等です。
アップデート
コメントとしては長すぎました。
ロバート、答えてくれてありがとう。私はすべてを消化しようとしていますが、これが私が行うことです-私は「大きな」配列を持っており、値を乗算し*2
て出力配列に格納する必要があります(ウォームアップとして;ところで、私が行うすべての計算は数学的に正しいです)。したがって、最初にこれを1ブロック、1スレッドで実行します。罰金。次に、各乗算が1つのスレッドで1回だけ行われるように作業を分割しようとしました。その結果、私のプログラムの実行速度は約6倍遅くなります。GPUに関する情報を取得し、使用するブロックとスレッドの数を計算し、単一の乗算の代わりに各スレッド内で、配列内のオフセットを計算するためだけに約10の追加の乗算があるため、理由がわかります。スレッド。一方では、その望ましくない動作を変更する方法を見つけようとします。他方では、スレッドの「テール」をSM間で均等に広げたいと思います。
言い換えれば、私は間違っているかもしれませんが、これを解決したいと思います。私には1G*2
の小さな仕事があります(それだけです)-1Kスレッドで1Kブロックを作成するか、1スレッドで1Mブロックを作成するか、1Mスレッドで1ブロックを作成する必要があります。これまでのところ、GPUプロパティを読み取り、分割、分割し、グリッド/ブロックの各次元の最大値(または計算するデータがない場合は必要な値)を盲目的に使用します。
コード
size
は入力および出力配列のサイズです。一般に:
output_array[i] = input_array[i]*2;
必要なブロック/スレッドの数を計算します。
size_t total_threads = props.maxThreadsPerMultiProcessor
* props.multiProcessorCount;
if (size<total_threads)
total_threads = size;
size_t total_blocks = 1+(total_threads-1)/props.maxThreadsPerBlock;
size_t threads_per_block = 1+(total_threads-1)/total_blocks;
props.maxGridSize
持っているとprops.maxThreadsDim
私は同様の方法でブロックとスレッドの寸法を計算します-fromtotal_blocks
とthreads_per_block
。
そして、キラー部分は、スレッド(スレッドの「内部」)のオフセットを計算します。
size_t offset = threadIdx.z;
size_t dim = blockDim.x;
offset += threadIdx.y*dim;
dim *= blockDim.y;
offset += threadIdx.z*dim;
dim *= blockDim.z;
offset += blockIdx.x*dim;
dim *= gridDim.x;
offset += blockIdx.y*dim;
dim *= gridDim.y;
size_t chunk = 1+(size-1)/dim;
これで、現在のスレッドの開始オフセットと、乗算用の配列(チャンク)内のデータ量がわかりました。grimDim.z
AFAIKは常に1なので、上記は使用しませんでしたね。