我有一个内核,它在Kepler和Fermi硬件上运行时显示不同块大小的最高性能。我想在编译时检查当前的体系结构目标并定义一个THREADS_PER_BLOCK
宏来i)启动内核; ii)确定所需的块数; iii)静态设置内核中的共享内存大小。
以下说明了我正在尝试做的事情。假设我的目标是GK104硬件,因此使用nvcc -arch=sm_30
。这仍将导致THREADS_PER_BLOCK = 256
,因为未为主机代码编译定义__CUDA_ARCH__
。 (我理解,从例如this answer,为什么它不能以这种方式工作。)
#if __CUDA_ARCH__ >= 300
#define THREADS_PER_BLOCK 512
#else
#define THREADS_PER_BLOCK 256
#endif
__global__ void some_kernel(int* a, int* b) {
__shared__ sm_data[THREADS_PER_BLOCK];
// Do something.
}
int main(void) {
// Initialize data.
// Calculate blocks based on THREADS_PER_BLOCK, problem size and some max.
some_kernel<<blocks, THREADS_PER_BLOCK>>>(d_a, d_b)
return 0;
}
我可以在运行时检查设备属性并使用动态共享内存,但是想知道这是否可以在编译时进行硬编码,而不需要例如必须手动添加-DFERMI或-DKEPLER并根据它设置THREADS_PER_BLOCK
。注意:此代码的任何用户都将自己编译,几乎当然对于一个架构,所以这不是一个不合理的选择。鉴于传递-arch=
旗帜,这似乎是多余的。
答案 0 :(得分:2)
nvcc
编译器未检测到本地可用的GPU,默认情况下始终以SM 1.0为目标。否则,在不同的系统上构建时可能会引入一些相当混乱的行为。
要编译可用设备,您需要要求用户指定SM版本或在构建期间运行一些检测代码。我确信将硬件检测代码放入运行时更容易,然后根据需要配置内核启动。