如果您有相同的条目点(例如内核名称、启动参数、参数相同),那么您可以依赖预编译器(这是来自 grabCut CUDA SDK 示例):
#if __CUDA_ARCH__ < 200
unsigned int gmm_flags_bvec = 0;
for (int i=0; i<32; ++i)
{
if (gmm_flags[i] > 0)
{
gmm_flags_bvec |= 1 << i;
}
}
tile_gmms[blockIdx.y * gridDim.x + blockIdx.x] = gmm_flags_bvec;
#else
tile_gmms[blockIdx.y * gridDim.x + blockIdx.x] = __ballot(gmm_flags[threadIdx.x] > 0);
#endif
那么你必须将几个 -gencode 参数传递给 NVCC - 它会构建不同的内核并将它们包含在你的可执行文件中。当应用程序运行时,驱动程序将自动为您的设备选择正确的内核。
然后,如果您的主机代码在不同的设备架构之间有所不同(例如,如果设备真的很旧,您可以在设备上执行较少的操作),您可以为不同的计算能力创建多个 CU - 并且每个 CU 文件都将导出主机函数作为条目观点。根据可用硬件使用正确的入口点将是您的应用程序的责任。
例如,您将拥有 application_logic_sm3x.cu,其中包含使用 SM 3.x 功能的内核和一个名为 compute_sm3x(...) 的常规 C 函数。Application_logic_sm2x.cu 将使用 SM 2.x 功能和一个名为 compute_sm2x(...) 的包含 C 函数。
您的 main.cpp 函数将使用 cudaGetDeviceProperties,然后根据可用硬件调用 compute_sm3x 或 compute_sm2x。
更新您可以查看 CUDA Toolkit 5.0 中的 simplePrintf 示例 - 它对于 1.x 和 2.x 及更高版本的代码路径略有不同。