我会用cudaMallocManaged
分配一些内存。我可以安全地将此指针传递给另一个程序模块(编译成另一个.o文件),该程序模块不知道CUDA,只会使用简单的memcpy或其他东西来操纵指针后面的数据吗?
像这样的东西
// compiled into A.o
class A{
void* getMem(int size){
void* ptr;
cudaMallocManaged(*ptr, size);
return ptr;
}
// some kernels here
}
// compiled into B.o
class B{
void manipulateMem(void* ptr, void* source, int size){
memcpy(ptr, source, size);
}
}
然后像这样的代码,可能编译成main.o:
A a;
B b;
void* mem = a.getMem(100);
b.manipulateMem(mem, source, 100);
我没有发现在这种情况下自动复制/同步不起作用的任何通知。
答案 0 :(得分:8)
我是否可以安全地将此指针传递给另一个程序模块(编译成另一个.o文件),该程序模块不知道CUDA,只会使用普通的memcpy或其他东西来操纵指针后面的数据?
是的,你可以,但Unified Memory access rules(< - 提示:点击这个并阅读此内容)仍然必须遵守。对于计算能力为3.0或更高但低于6.0的GPU,这些目前的规则是:
cudaMallocManaged
)之后,在调用任何内核之前,可以从主机CPU上运行的代码访问托管指针。cudaDeviceSynchronize()
,主机代码中的数据无法访问,任何在主机代码中使用它的尝试都将导致UB,可能包括seg故障。cudaDeviceSynchronize()
)之后,将恢复对托管指针引用的数据的主机访问。 (从技术上讲,在当前实现中,此时主机对数据的访问通常会导致页面错误,这是一个OS可见事件。这些页面错误基本上调用CUDA运行时,然后执行必要的cudaMemcpy
操作在引擎盖下,将数据返回给主机,以处理页面错误。但是括号中的这些注释对于理解行为的一般规则是不必要的。)因此,CUDA运行时基本上有明确的标记(内核启动 - >同步),它明确地标识了如何管理数据(何时迁移以及在哪个方向上)。因此,即使您在某些"模块中运行代码...但是不了解CUDA",如果遵守上述规则,该模块中的代码将可以访问数据,因为CUDA运行时具有足够的显式标记,用于标识如何管理数据。
对于计算能力为6.0或更高的GPU,上述规则基本上不适用。对于这些GPU,主机和设备的并发访问是可能的,但是对公共资源的多次访问仍然存在竞争条件的可能性,如在任何多处理器/多线程环境中那样。 目前,CUDA运行时不会强制主机和设备访问同一页内存之间的任何特定访问排序规则。
答案 1 :(得分:1)
是的,CUDA统一内存模型明确允许这种访问:GPU不仅可以直接访问统一内存指针。以相同的方式,在主机CPU上运行的程序的一部分将具有包括GPU存储器的统一访问。但请注意总线带宽瓶颈。