2

私はCUDAが初めてで、多数の配列を処理しようとしています。各配列は約 1000 文字の配列 (文字列ではなく、単に文字として格納されます) であり、最大 100 万個まで存在する可能性があるため、約 1 GB のデータが転送されます。このデータはすでにすべてメモリにロードされており、各配列へのポインタがありますが、すべてのデータがメモリ内で連続しているとは思えないため、1 回の呼び出しですべてを転送することはできません。

私は現在、推力で最初に取り組み、このメッセージに基づいてソリューション を作成しました...すべてのメモリを割り当てる静的呼び出しで構造体を作成し、個々のコンストラクターがその配列をコピーしました。デバイス配列へのポインターを持つ構造体を取り込む変換呼び出し。

私の問題は、各配列が個別にコピーされるため、これが明らかに非常に遅いことです。このデータをより速く転送する方法を考えています。

この質問(質問はほとんど関係ありませんが、ユーザーは似たようなことをしようとしていると思います) で、talonmies は zip イテレーターを試して使用することを提案していますが、それが多数の配列の転送にどのように役立つかわかりません。

この質問を書いているときに cudaMemcpy2DToArray と cudaMemcpy2D についても知ったので、おそらくそれらが答えですが、どちらもポインターへのポインターを入力として受け取らないように見えるため、これらがどのように機能するかはすぐにはわかりません...

どんな提案も大歓迎です...

4

3 に答える 3

1

非同期を試してみてください。同じジョブを異なるストリームに割り当てることができます。各ストリームは日付のごく一部を処理し、転送と計算を同時に行い
ます。コードは次のとおりです。

cudaMemcpyAsync(
    inputDevPtr + i * size, hostPtr + i * size, size, cudaMemcpyHostToDevice, stream[i]
);
MyKernel<<<100, 512, 0, stream[i]>>> (outputDevPtr + i * size, inputDevPtr + i * size, size);
cudaMemcpyAsync(
    hostPtr + i * size, outputDevPtr + i * size, size, cudaMemcpyDeviceToHost, stream[i]
);
于 2012-05-22T08:55:54.927 に答える
1

これを行う 1 つの方法は、marina.k が提案したように、必要なときにのみ転送をバッチ処理することです。各配列には約1000文字しか含まれていないと言ったので、各文字をスレッドに割り当て(Fermiではブロックごとに1024スレッドを割り当てることができるため)、各配列を1つのブロックで処理することができます。この場合、1 回の呼び出しで 1 つの「ラウンド」のすべての配列を転送できる場合があります。1 つの巨大な配列を作成し、「3 番目の」1000 文字配列の 5 番目の要素を取得する FORTRAN スタイルを使用できますか?行く:

third_array[5] = big_array[5 + 2*1000]

最初の 1000 文字配列が big_array の最初の 1000 要素を構成し、2 番目の 1000 文字配列が big_array の 2 番目の 1000 要素を構成するようにします。この場合、文字はメモリ内で連続しており、1 つの memcpy で 1 回のカーネル起動で処理しようとしていたセットを移動できます。次に、1 つのカーネルを起動するとすぐに、CPU 側で big_array を補充し、非同期で GPU にコピーします。

各カーネル内では、各配列を 1 ブロック内で単純に処理できるため、ブロック N は (N-1) 番目の要素から d_big_array の N 番目 (これらすべての文字をコピーした場所) までを処理します。

于 2012-05-14T23:22:32.110 に答える
1

固定メモリを試しましたか?これにより、一部のハードウェア構成でかなりのスピードアップが得られる場合があります。

于 2012-05-15T20:29:30.423 に答える