6

cudaランタイムAPIアプリケーションでcudaコンテキストが作成され、カーネルに関連付けられる方法を理解したいですか?

私はそれがドライバーAPIによって内部で行われていることを知っています。しかし、私は作成のタイムラインを理解したいと思います。

まず、cudaRegisterFatBinaryが最初に行われたcuda api呼び出しであり、実行時にfatbinファイルを登録することを知っています。その後に、ドライバー層でcuModuleLoadを呼び出すいくつかのcuda関数登録APIが続きます。しかし、私のCudaランタイムAPIアプリケーションがcudaMallocを呼び出す場合、コンテキストに関連付けられたこの関数へのポインターはどのように提供されますか。これは事前に作成されているはずです。このすでに作成されたコンテキストへのハンドルを取得し、将来のランタイムAPI呼び出しをそれに関連付けるにはどうすればよいですか?内部の仕組みをわかりやすく説明してください。

これに関するNVIDIAのドキュメントを引用するには

CUDAランタイムAPI呼び出しは、現在のホストスレッドにバインドされているCUDAドライバーAPICUcontextで動作します。

CUcontextを必要とするCUDAランタイムAPI呼び出し時に、現在のスレッドにバインドされたCUDAドライバーAPI CUcontextが存在しない場合、CUDAランタイムは呼び出しを実行する前に暗黙的に新しいCUcontextを作成します。

CUDAランタイムがCUcontextを作成する場合、CUcontextは、CUDAランタイムAPI関数cudaSetDevice、cudaSetValidDevices、cudaSetDeviceFlags、cudaGLSetGLDevice、cudaD3D9SetDirect3DDevice、cudaD3D10SetDirect3DDevice、およびcudaD3D11SetDirect3DDeviceによって指定されたパラメーターを使用して作成されます。これらの関数は、CUcontextが現在のホストスレッドにバインドされているときに呼び出された場合、cudaErrorSetOnActiveProcessで失敗することに注意してください。

CUcontextの存続期間は、参照カウントメカニズムによって管理されます。CUcontextの参照カウントは最初は0に設定され、cuCtxAttachによってインクリメントされ、cuCtxDetachによってデクリメントされます。

CUDAランタイムによってCUcontextが作成された場合、CUDAランタイムは関数cudaThreadExitでそのCUcontextの参照カウントをデクリメントします。CUcontextがCUDADriverAPIによって作成された場合(またはCUDA Runtime APIライブラリの別のインスタンスによって作成された場合)、CUDARuntimeはそのCUcontextの参照カウントをインクリメントまたはデクリメントしません。

すべてのCUDAランタイムAPIの状態(グローバル変数のアドレスや値など)は、基礎となるCUcontextとともに移動します。特に、CUcontextが1つのスレッドから別のスレッドに移動されると(cuCtxPopCurrentとcuCtxPushCurrentを使用)、すべてのCUDAランタイムAPIの状態もそのスレッドに移動します。

しかし、私が理解していないのは、cudaランタイムがどのようにコンテキストを作成するのかということです。これにはどのAPI呼び出しが使用されますか?nvccコンパイラはコンパイル時にこれを行うためにいくつかのAPI呼び出しを挿入しますか、それともこれは完全に実行時に行われますか?前者が当てはまる場合、このコンテキスト管理に使用されるランタイムAPIは何ですか?後者はどのように正確に行われているのですか?

コンテキストがホストスレッドに関連付けられている場合、このコンテキストにアクセスするにはどうすればよいですか?スレッドによって処理されるすべての変数とポインター参照に自動的に関連付けられていますか?

最終的に、モジュールのロードはコンテキストでどのように行われますか?

4

1 に答える 1

3

CUDAランタイムは、ロードするモジュールのグローバルリストを維持し、CUDAランタイムを使用するDLLまたは.soがプロセスにロードされるたびにそのリストに追加されます。ただし、デバイスが作成されるまで、モジュールは実際にはロードされません。

コンテキストの作成と初期化は、CUDAランタイムによって「遅延」で行われます。cudaMemcpy()などの関数を呼び出すたびに、CUDAが初期化されているかどうかを確認し、初期化されていない場合は、コンテキストを作成します(以前にcudaSetDevice()によって指定されたデバイス、またはcudaSetDevice()が呼び出されなかった場合はデフォルトのデバイス)、すべてのモジュールをロードします。コンテキストは、cudaSetDevice()によって変更されるまで、それ以降、そのCPUスレッドに関連付けられます。

cuCtxPopCurrent()/ cuCtxPushCurrent()などのドライバーAPIのコンテキスト/スレッド管理関数を使用して、別のスレッドのコンテキストを使用できます。

cudaFree(0);を呼び出すことができます。この遅延初期化を強制的に発生させます。

競合状態や未定義の動作を避けるために、アプリケーションの初期化時にそうすることを強くお勧めします。先に進み、アプリでできるだけ早くデバイスを列挙して初期化します。それが完了すると、CUDA 4.0では任意のCPUスレッドからcudaSetDevice()を呼び出すことができ、初期化コードによって作成された対応するコンテキストが選択されます。

于 2011-09-24T18:43:49.573 に答える