调用cudaFree(0)是否被CUDA规范保证会产生实际作用?
关于cudaFree(0)的官方行为说明
cudaFree(0)的行为是完全被CUDA官方API规范保证的,不存在“非官方约定”的不确定性问题。
根据CUDA Runtime API的明确定义:当向cudaFree传入空指针(即数值0或者NULL)时,接口不会执行任何实际的内存释放操作,也不会产生额外的内存开销,但是会完整走一遍Runtime API的调用流程:如果当前线程尚未绑定有效的CUDA上下文,该调用会自动完成上下文的创建、初始化以及线程绑定操作,最终返回的状态码为cudaSuccess。
这个用法流行的核心原因是CUDA Runtime默认采用延迟初始化策略:上下文不会在程序启动时就创建,只会在第一次调用非查询类Runtime API时才触发初始化。其他常见的触发初始化的API比如cudaMalloc、cudaMemcpy、核函数启动等,要么会产生内存分配/拷贝的额外开销,要么有其他业务侧的副作用,只有cudaFree(0)是几乎没有额外开销、也不会干扰业务逻辑的最轻量初始化方案,这也是很多官方示例、历史项目都会用到这个写法的原因。
目前对这个用法的争议基本都集中在代码可读性层面:这个写法利用了API的副作用实现初始化,语义不够直观,没有相关经验的开发者很难第一时间理解这段代码的作用。现在更推荐用语义更清晰的cudaSetDevice()之类的显式接口完成初始化,代码可维护性更好。
截止到最新的CUDA 12.x版本,cudaFree(0)的上述行为也没有被修改,也没有被标记为废弃特性,现有代码中的相关用法可以正常运行,不需要特意改造。
内容的提问来源于stack exchange,提问作者einpoklum

