6

問題

.hがあるので、c / c ++またはコンピューティング機能が1.3以上のcudaでコンパイルする場合は、realをdoubleと定義したいと思います。コンピューティング機能が1.3未満のcuda用にコンパイルする場合は、realをfloatとして定義します。

何時間も経って、私はこれに到達しました(これは機能しません)

#定義されている場合(__CUDACC__)

#警告*cudaの定義を作成する

#定義されている場合(__CUDA_ARCH__)
#警告__CUDA_ARCH__が定義されています
# そうしないと
#警告__CUDA_ARCH__が定義されていません
#endif

#if(__CUDA_ARCH__> = 130)
#リアルダブルを定義する
#cudaでdoubleを使用した警告
#elif(__CUDA_ARCH__> = 0)
#実際のフロートを定義する
#cudaでfloatを使用した警告
#__ CUDA_ARCH__が定義されていない場合、これがどのように出力されるかを警告しますか?
# そうしないと
#本物を定義する
#エラー__CUDA_ARCH__の値とは何ですか?どうすればそれを印刷できますか
#endif

# そうしないと
#警告* c /c++の定義を作成する
#リアルダブルを定義する
#c /c++にdoubleを使用した警告
#endif

コンパイルするとき(-archフラグに注意してください)

nvcc -arch Compute_13 -Ilibcutil testFloatDouble.cu 

私は得る

*cudaの定義を作成する
__CUDA_ARCH__が定義されています
cudaでdoubleを使用する

*cudaの定義を作成する
警告__CUDA_ARCH__が定義されていません
cudaでfloatを使用した警告
__CUDA_ARCH__が現在定義されていない場合、これはどのように出力されますか?

アーキテクチャi386の未定義のシンボル:
  "myKernel(float *、int)"、参照元:...。

私はファイルがnvccによって2回コンパイルされることを知っています。最初のものはOKです(CUDACCが定義され、CUDA_ARCH > = 130)が、2回目はどうなりますか? CUDA_DEFINEDですが、CUDA_ARCHが定義されていないか、値が130未満ですか?なんで ?

御時間ありがとうございます。

4

2 に答える 2

31

nvccがCUDAコードを処理しているときにホストとデバイスのコンパイル軌跡を区別する方法と、CUDAコードと非CUDAコードを区別する方法の2つを混同しているようです。2つの間に微妙な違いがあります。__CUDA_ARCH__最初の質問に__CUDACC__答え、2番目の質問に答えます。

次のコードスニペットについて考えてみます。

#ifdef __CUDACC__
#warning using nvcc

template <typename T>
__global__ void add(T *x, T *y, T *z)
{
    int idx = threadIdx.x + blockDim.x * blockIdx.x;

    z[idx] = x[idx] + y[idx];
}

#ifdef __CUDA_ARCH__
#warning device code trajectory
#if __CUDA_ARCH__ > 120
#warning compiling with double precision
template void add<double>(double *, double *, double *);
#else
#warning compiling with single precision
template void add<float>(float *, float *, float *);
#else
#warning nvcc host code trajectory
#endif
#else
#warning non-nvcc code trajectory
#endif

ここに、CUDAアーキテクチャに依存するインスタンス化を備えたテンプレート化されたCUDAカーネル、によって操作されるホストコード用の個別のスタンザnvcc、およびによって操作されないホストコードのコンパイル用のスタンザがありますnvcc。これは次のように動作します。

$ ln -s cudaarch.cu cudaarch.cc
$ gcc -c cudaarch.cc -o cudaarch.o
cudaarch.cc:26:2: warning: #warning non-nvcc code trajectory

$ nvcc -arch=sm_11 -Xptxas="-v" -c cudaarch.cu -o cudaarch.cu.o
cudaarch.cu:3:2: warning: #warning using nvcc
cudaarch.cu:14:2: warning: #warning device code trajectory
cudaarch.cu:19:2: warning: #warning compiling with single precision
cudaarch.cu:3:2: warning: #warning using nvcc
cudaarch.cu:23:2: warning: #warning nvcc host code trajectory
ptxas info    : Compiling entry function '_Z3addIfEvPT_S1_S1_' for 'sm_11'
ptxas info    : Used 4 registers, 12+16 bytes smem

$ nvcc -arch=sm_20 -Xptxas="-v" -c cudaarch.cu -o cudaarch.cu.o
cudaarch.cu:3:2: warning: #warning using nvcc
cudaarch.cu:14:2: warning: #warning device code trajectory
cudaarch.cu:16:2: warning: #warning compiling with double precision
cudaarch.cu:3:2: warning: #warning using nvcc
cudaarch.cu:23:2: warning: #warning nvcc host code trajectory
ptxas info    : Compiling entry function '_Z3addIdEvPT_S1_S1_' for 'sm_20'
ptxas info    : Used 8 registers, 44 bytes cmem[0]

これからのポイントは次のとおりです。

  • __CUDACC__nvccステアリングコンパイルかどうかを定義します
  • __CUDA_ARCH__ホストコードをコンパイルするときは常にnvcc未定義です。
  • __CUDA_ARCH__によって操作されるコンパイルのデバイスコード軌道に対してのみ定義されますnvcc

これらの3つの情報は、さまざまなCUDAアーキテクチャへのデバイスコード、ホスト側のCUDAコード、およびまったくコンパイルされていないコードの条件付きコンパイルを行うのに常に十分ですnvccnvccドキュメントは時々少し簡潔ですが、これらすべてはコンパイルの軌跡に関する議論でカバーされています。

于 2012-01-10T20:17:16.237 に答える
3

今のところ、私が見る唯一の実用的な解決策は、カスタム定義を使用することです。

#if(!defined(__ CUDACC__)|| defined(USE_DOUBLE_IN_CUDA))
#リアルダブルを定義する
#cudaまたはc /c++のdoubleを定義する警告
# そうしないと
#実際のフロートを定義する
#cudaのフロートを定義する警告
#endif

その後

nvcc -DUSE_DOUBLE_IN_CUDA -arch Compute_13 -Ilibcutil testFloatDouble.cu

2つのコンパイルのを出力するとき:

#cudaまたはc/c++のdoubleを定義する警告
#cudaまたはc/c++のdoubleを定義する警告

nvcc -Ilibcutil testFloatDouble.cu 

します

#cudaのフロートを定義する警告
#cudaのフロートを定義する警告
于 2012-01-09T23:40:05.687 に答える