0

私は生物物理学の大学院生で、PyCUDA と Scipy を使用してタンパク質凝集モデルをプログラムしようとしていODEIntます。過去 2 週間以内に、コードを実行できるようになりましたが、非常に遅いです。私のコードが何をするのか説明できるかどうか見てみましょう。

各要素が長さのポリマーの濃度である濃度のnp配列があります。各カーネルが特定の長さのポリマーの変化率を計算する場所を使用して、ポリマー濃度の変化率を計算する関数があります。この計算中に、長さの配列をスレッドで合計する必要があるため、コードが大幅に遅くなります。Ni+1CUDA(N-i-1)

少し読んでグーグルで調べてみると、並列処理を呼び出して配列の合計などのシリアル計算をはるかに高速化する方法として、並列削減に出くわしました。もちろん、私はマーク・ハリスのパワーポイントのスライドを参照しています. これらは素晴らしい読み物であり、これは私のコードを劇的に高速化する潜在的な方法のように見えますが、いくつか質問があります:

ポリマー種の数 N が ~ 8700 ~ 9000 である必要がある場合、CUDA を使用してこれらの N 配列を同時に削減することは考えられますか? 簡単な計算を行うと (同時スレッドの最大数を計算する方法に関する SO の優れた説明のおかげで可能になりました)、GTX Titan で一度に 15 * 64 * 32 = 30720 のスレッドを実行できることがわかりました。一度に最大 8960 個のカーネルでカーネルを呼び出すと、使用できるスレッドは 21760 個しか残っていないはずですよね? それを適切に削減するには、少なくとも (配列の長さ/2) スレッドが必要なように思われるので、私は絶望的です。

残りのスレッドを分割して、一度にいくつかの大きな配列をシリアルに削減することで、残りのスレッドを使用できるのではないかと考えていました。

わかりません...私はただの物理学の大学院生です。間違った方向への長い旅に出る前に、専門家に聞いてみようと思いました. カーネルに何かを減らすように簡単かつ効率的に伝えることは可能ですか?

ありがとう、カルステン

これが私がやろうとしていることの表現です。

fluxes and concs are np.arrays
dcdt(concs, t)
    Call CUDA to calculate fluxes
        Thread
        0       fluxes[i] = stuff + sum(concs[n] for n from 1 to 9000)
        1       fluxes[i] = stuff + sum(concs[n] for n from 2 to 9000)
        2       fluxes[i] = stuff + sum(concs[n] for n from 3 to 9000)
        ...
        N       fluxes[i] = stuff

これまで説明してきた配列の合計は、基本的に各スレッドの同じ配列のより小さいバージョンであることに気付くでしょう。これは、これがホスト上で行うべきことなのかどうか疑問に思います。

4

1 に答える 1

1

CUDA を使用して複数の配列を「並列に」削減することが考えられます。リダクション (合計) はそれほど計算集約型の操作ではないため、データがまだ GPU に常駐していない場合、GPU にデータを転送するためのコストは、全体のかなりの部分 (大部分) になる可能性があります。実行時間。あなたの説明から、GPUで何らかの方法でこれをすでに行っているのか、CPUで行っているのかは明確ではありません。ただし、データが GPU 上にある場合は、並列削減による合計が最も高速になります。

1 つの配列のデータが 2GB を超えない限り、スレッド数は問題になりません。

配列を次々と単純に削減するカーネルを作成できます。N 個の配列があると言っているようですが、N は約 9000 です。各配列の大きさはどれくらいですか? 配列が十分に大きい場合、GPU のほぼすべての能力 (大まかに言えば) を個々の操作に適用できます。その場合、配列を次々に削減しても大きなペナルティはありません。カーネルは、配列をループする基本的な並列削減である可能性があります。かなり簡単なはずです。

約 9000 個の配列を処理する必要があり、インターリーブ方式でデータを並べ替えることが難しくない場合は、9000 個のスレッドの配列を検討することもできます。この場合、各スレッドは単一の配列の要素をシリアル ループで合計します。 CPUコードで単純に行う方法。このすべての目標は、利用可能なメモリ帯域幅を最大限に活用することであるため、ここではデータ編成が重要です。各スレッドのループは合計される次のデータ要素を取得しているため、ワープ (合体アクセス) 内のスレッド間で連続したデータ読み取りがあることを確認し、N 配列間でインターリーブされたデータ ストレージ配置を意味します。その場合、このアプローチも非常に高速に実行されます。

ところで、比較的使いやすく、配列の総和を削減するための簡単な操作を提供する、推力を見てみることもできます。プロトタイプとして、GPU で配列のシーケンスを繰り返し合計するスラスト コードにループを記述することは比較的簡単です。

于 2013-05-14T21:43:59.307 に答える