2

非常に長くまとまりのない関数を避けるために、カーネルから多くのデバイス関数を呼び出しています。カーネル呼び出し (スレッド ブロックごと) の開始時に共有バッファーを割り当て、カーネルでいくつかの処理ステップを実行しているすべてのデバイス関数にポインターを渡します。

私は次のことについて疑問に思っていました:

グローバル関数で共有メモリ バッファを割り当てた場合、ポインタを渡す他のデバイス関数は、ポインタが参照できる可能性のあるアドレス タイプ (グローバル デバイスまたは共有メモリ) をどのように区別できますか。

「CUDA プログラミング ガイド」に従って、共有修飾子で仮パラメータを装飾することは無効であることに注意してください。imhoit を実装できる唯一の方法は

a)割り当てられたメモリにマーカーを配置する b)呼び出しで非表示のパラメーターを渡す。c) グローバルメモリと共有メモリ用に別々のセグメントを持つ仮想統合アドレス空間を持ち、ポインタのしきい値チェックを使用できますか?

だから私の質問は次のとおりです:私はそれについて心配する必要がありますか、それともすべての関数をメインカーネルにインライン化せずに別の方法で進める必要がありますか?

================================================== =========================================

一方、私は今日、CUDA Toolkit 3.0 を使用した NVCC が、いわゆる「グローバル関数からの外部呼び出し」を許可せず、インライン化する必要があることに恐怖を感じました。これは、事実上、すべてのデバイス関数をインラインで宣言する必要があり、ヘッダーとソース ファイルの分離が壊れていることを意味します。これはもちろん非常に醜いですが、代替手段はありますか?

4

2 に答える 2

1

グローバル関数で共有メモリ バッファを割り当てた場合、ポインタを渡す他のデバイス関数は、ポインタが参照できる可能性のあるアドレス タイプ (グローバル デバイスまたは共有メモリ) をどのように区別できますか。

CUDA のコンテキストにおける「共有」メモリとは、ブロック内のすべてのスレッド間で共有されるオンチップ メモリを意味することに注意してください。したがって、__shared__修飾子で宣言された配列を意味する場合、デバイス関数間で情報を渡すためにそれを使用することは通常意味がありません (すべてのスレッドがまったく同じメモリを参照するため)。コンパイラが通常の配列を共有メモリに配置する可能性があると思いますか? または、レジスタファイルにあった可能性があります。いずれにせよ、最終的にグローバル メモリになる可能性が高く、これはデバイス関数間で情報を渡す非効率的な方法です (特に 2.0 未満のデバイスでは)。

一方、CUDA ツールキット 3.0 を使用した NVCC では、いわゆる「グローバル関数からの外部呼び出し」が許可されておらず、インライン化する必要があることに、今日は恐怖を感じました。これは、事実上、すべてのデバイス関数をインラインで宣言する必要があり、ヘッダーとソース ファイルの分離が壊れていることを意味します。これはもちろん非常に醜いですが、代替手段はありますか?

CUDA にはデバイス コードのリンカーが含まれていないため、カーネルと関連するすべてのデバイス関数を同じ .cu ファイルに保持する必要があります。

于 2012-06-07T16:11:04.233 に答える
0

これは、CUDAデバイスの計算能力によって異なります。計算能力が2.0未満のデバイスの場合、コンパイラはコンパイル時に、ポインタが共有メモリとグローバルメモリのどちらを指しているかを判断し、個別の命令を発行する必要があります。これは、コンピューティング機能が2.0以上のデバイスには必要ありません。

デフォルトでは、カーネル内のすべての関数呼び出しがインライン化され、コンパイラーはほとんどの場合、フロー分析を使用して、何かが共有されているかグローバルであるかを確認できます。計算能力が2.0未満のデバイス用にコンパイルしている場合は、警告が発生している可能性がありますwarning : Cannot tell what pointer points to, assuming global memory space。これは、コンパイラーがポインターを正しく追跡できない場合に得られるものです。

于 2012-06-07T15:11:14.410 に答える