我试图在方便的统一内存模型下实现CUDA功能的动态绑定。这里,我们有一个包含成员的struct Parameters ,一个函数指针void(* p_func)()。
#include <cstdio>
struct Parameters {
void (*p_func)();
};
结构由统一内存管理,我们将实际函数 func_A 分配给 p_func 。
__host__ __device__
void func_A() {
printf("func_A is correctly invoked!\n");
return;
}
当我们通过以下代码时,出现问题:如果分配1运行,即 para-> p_func = func_A ,则设备和主机功能地址实际上都是由功能地址分配的在主持人。相反,如果赋值2运行,则地址都将成为设备地址。
__global__ void assign_func_pointer(Parameters* para) {
para->p_func = func_A;
}
__global__ void run_on_device(Parameters* para) {
printf("run on device with address %p\n", para->p_func);
para->p_func();
}
void run_on_host(Parameters* para) {
printf("run on host with address %p\n", para->p_func);
para->p_func();
}
int main(int argc, char* argv[]) {
Parameters* para;
cudaMallocManaged(¶, sizeof(Parameters));
// assignment 1, if we uncomment this section, p_func points to address at host
para->p_func = func_A;
printf("addr@host: %p\n", para->p_func);
// assignment 2, if we uncomment this section, p_func points to address at device
assign_func_pointer<<<1,1>>>(para); //
cudaDeviceSynchronize();
printf("addr@device: %p\n", para->p_func);
run_on_device<<<1,1>>>(para);
cudaDeviceSynchronize();
run_on_host(para);
cudaFree(para);
return 0;
}
现在的问题是,在统一内存模型下,设备和主机上的函数指针是否可能分别指向正确的函数地址?
答案 0 :(得分:1)
暂时不考虑统一内存的技术性,你的问题实际上是“一个变量可以同时具有两个不同的值吗?”对此的答案显然不是。
更详细地说:CUDA统一内存从根本上确保了当从主机和设备访问时,给定的托管分配将具有一致的值(在某些约束下)。你要求的是完全相反的,显然不支持。
答案 1 :(得分:1)
对struct
定义进行一些修改后,可能会出现类似的情况:
$ cat t1288.cu
#include <cstdio>
struct Parameters {
void (*p_hfunc)();
void (*p_dfunc)();
__host__ __device__
void p_func(){
#ifdef __CUDA_ARCH__
(*p_dfunc)();
#else
(*p_hfunc)();
#endif
}
};
__host__ __device__
void func_A() {
printf("func_A is correctly invoked!\n");
return;
}
__global__ void assign_func_pointer(Parameters* para) {
para->p_dfunc = func_A;
}
__global__ void run_on_device(Parameters* para) {
printf("run on device\n"); // with address %p\n", para->p_dfunc);
para->p_func();
}
void run_on_host(Parameters* para) {
printf("run on host\n"); // with address %p\n", para->p_func);
para->p_func();
}
int main(int argc, char* argv[]) {
Parameters* para;
cudaMallocManaged(¶, sizeof(Parameters));
// assignment 1, if we uncomment this section, p_func points to address at host
para->p_hfunc = func_A;
printf("addr@host: %p\n", para->p_hfunc);
// assignment 2, if we uncomment this section, p_func points to address at device
assign_func_pointer<<<1,1>>>(para); //
cudaDeviceSynchronize();
printf("addr@device: %p\n", para->p_dfunc);
run_on_device<<<1,1>>>(para);
cudaDeviceSynchronize();
run_on_host(para);
cudaFree(para);
return 0;
}
$ nvcc -arch=sm_35 -o t1288 t1288.cu
$ cuda-memcheck ./t1288
========= CUDA-MEMCHECK
addr@host: 0x402add
addr@device: 0x8
run on device
func_A is correctly invoked!
run on host
func_A is correctly invoked!
========= ERROR SUMMARY: 0 errors
$
我同意另一个答案,即使使用托管内存,目前也无法使用单个数字函数指针,该指针在主机代码和设备代码中都能正常工作。