我正在尝试编写一个模拟浮点数和双精度数的CUDA应用程序,因为我希望能够在单精度卡和双精度卡上运行。该应用程序使用动态分配的全局,动态分配的共享,以及常量内存和静态全局内存。
我已经看到了模板化动态分配的全局和共享内存变量的示例。我意识到常量内存是静态的,因此通常不可能进行模板化,如本文所述:Defining templated constant variables in cuda。
我一直无法找到这个常量内存问题的任何变通方法,这让我感到惊讶,因为我确信我不是第一个遇到这个问题的人。目前,我似乎要面对必须写同一个应用程序的两个副本,一个用于双打,一个用于浮点数,如果我想使用常量内存。我希望情况并非如此。
作为一种解决方法,我正在考虑编写一个模板化的(虚拟?)基类,并实现除常量内存变量声明之外的所有内容。然后我想编写两个继承自base的类(一个用于浮点数,一个用于双精度数),主要用于处理常量变量声明。我的问题是这个策略是否有效或是否有明显的缺陷?我只是想在实现设计之前我会问,但发现它不起作用。如果这种策略不起作用,是否还有其他经过验证的策略至少可以缓解这个问题?或者我只需要编写应用程序的两个副本,一个用于浮动,一个用于双倍?
答案 0 :(得分:2)
请注意,此答案仅具有历史意义,或者对于使用CUDA工具包6.5或更早版本的用户而言。自CUDA 7.0起,没有支持float
的受支持的CUDA设备,因此nvcc
CUDA编译器不再保留下述功能,以自动将double
降级为float
。
由于您提到您只关注float
和double
,并且您提到您只关注float
不支持double
的设备,似乎你可以利用nvcc
编译器automatic demotion of double to float来处理这个问题。
以下是使用__constant__
内存的示例:
$ cat t264.cu
#include <stdio.h>
#define DSIZE 64
__constant__ double my_const_data[DSIZE];
__global__ void my_kernel(double *data){
data[1] = my_const_data[0];
data[0] = sqrt(my_const_data[0]);
}
int main(){
double my_data[DSIZE], h_data[DSIZE], *d_data;
my_data[0] = 256.0;
cudaMemcpyToSymbol(my_const_data, my_data, sizeof(double)*DSIZE);
printf("hello\n");
cudaMalloc((void **)&d_data, sizeof(double)*DSIZE);
my_kernel<<<1,1>>>(d_data);
cudaMemcpy(&h_data, d_data, sizeof(double)*DSIZE, cudaMemcpyDeviceToHost);
printf("data = %lf\n", h_data[1]);
printf("sqrt = %lf\n", h_data[0]);
return 0;
}
$ nvcc -o t264 t264.cu
ptxas /tmp/tmpxft_00003228_00000000-5_t264.ptx, line 62; warning : Double is not supported. Demoting to float
$ ./t264
hello
data = 256.000000
sqrt = 16.000000
$