cudaPointerGetAttributes()对主机指针返回无效参数的原因及指针判断函数问题
封装cudaPointerGetAttributes()判断指针类型(处理主机指针的错误问题)
我来帮你解决这个封装函数的问题!你遇到的困惑其实是CUDA API的特性导致的——cudaPointerGetAttributes()并不是能识别所有主机指针,它只认CUDA管理过的指针(比如cudaMalloc分配的设备指针、cudaMallocHost分配的页锁定主机指针,或者cudaHostRegister注册过的普通主机指针),普通malloc出来的主机指针不在它的处理范围内,所以会返回cudaErrorInvalidValue错误。
我们可以通过手动捕获这个特定错误,来区分普通主机指针和其他类型指针,下面是完整的实现方案:
1. 完善错误检查宏
首先补全你定义的CUDA_ERROR_CHECK宏,让它能正确打印错误信息:
#include <stdio.h> #include <stdlib.h> #define CUDA_ERROR_CHECK(fun) \ do{ \ cudaError_t err = fun; \ if(err != cudaSuccess){ \ fprintf(stderr, "CUDA error at %s:%d: %s\n", __FILE__, __LINE__, cudaGetErrorString(err)); \ // 这里可以根据需求选择是否退出程序,或者返回错误码 // exit(EXIT_FAILURE); \ } \ }while(0)
2. 封装判断函数
我们在函数里先调用cudaPointerGetAttributes(),手动处理cudaErrorInvalidValue错误,再判断指针类型:
int isDevicePointer(void* ptr) { // 先处理NULL指针的情况(可选,根据你的需求调整) if (ptr == NULL) { fprintf(stderr, "Error: NULL pointer passed\n"); return -1; // 返回特殊值表示NULL指针 } cudaPointerAttributes attr; cudaError_t err = cudaPointerGetAttributes(&attr, ptr); // 普通主机指针(未被CUDA管理)会返回这个错误 if (err == cudaErrorInvalidValue) { return 0; } // 检查其他非预期错误 CUDA_ERROR_CHECK(err); // 判断是否为设备指针 return (attr.type == cudaMemoryTypeDevice) ? 1 : 0; }
3. 测试代码
下面是测试不同类型指针的示例:
int main() { // 测试设备指针 void* dev_ptr; CUDA_ERROR_CHECK(cudaMalloc(&dev_ptr, 1024)); printf("Device pointer result: %d\n", isDevicePointer(dev_ptr)); // 输出1 // 测试普通主机指针 void* host_ptr = malloc(1024); printf("Normal host pointer result: %d\n", isDevicePointer(host_ptr)); // 输出0 // 测试页锁定主机指针(CUDA管理的主机指针) void* pinned_host_ptr; CUDA_ERROR_CHECK(cudaMallocHost(&pinned_host_ptr, 1024)); printf("Pinned host pointer result: %d\n", isDevicePointer(pinned_host_ptr)); // 输出0 // 资源清理 CUDA_ERROR_CHECK(cudaFree(dev_ptr)); free(host_ptr); CUDA_ERROR_CHECK(cudaFreeHost(pinned_host_ptr)); return 0; }
关键注意点
cudaPointerGetAttributes()从CUDA 3.2版本开始支持,几乎所有现代CUDA版本都兼容- 如果不需要区分NULL指针,可以去掉开头的NULL判断逻辑
- 错误处理部分可以根据你的项目需求调整,比如在遇到非预期错误时直接退出程序,或者返回错误码让上层处理
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

