Возможно, вы путаете две вещи: как различать траектории компиляции хоста и устройства, когда nvcc обрабатывает код CUDA, и как различать код CUDA и код, отличный от CUDA. Между ними есть тонкая разница. __CUDA_ARCH__
отвечает на первый вопрос, а __CUDACC__
отвечает на второй.
Рассмотрим следующий фрагмент кода:
#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
Этих трех частей информации всегда достаточно для условной компиляции кода устройства для различных архитектур CUDA, кода CUDA на стороне хоста и кода, не скомпилированного nvcc
вообще. Документация nvcc
иногда немного лаконична, но все это рассматривается в обсуждении траекторий компиляции.