You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CUDA程序无提示失败排查:cudaMemcpyDeviceToHost始终返回全零值

CUDA程序无提示失败排查:cudaMemcpyDeviceToHost始终返回全零值

我太懂这种想验证CUDA环境却卡壳的憋屈感了!你这个程序跑出来全零的问题,一眼就能看到几个关键漏洞,咱们一步步捋:

最核心的问题:核函数根本没被调用!

你定义了write4这个GPU核函数,但在main里完全没启动它啊!GPU端的代码不会自动执行,必须用CUDA专属的核函数启动语法<<<网格大小, 块大小>>>来触发。GPU没干活,设备内存d_out里全是未初始化的垃圾值,拷贝回主机自然是零(或者随机值,你这里刚好是零而已)。

第二大问题:错误检查太不完整

你只给cudaMalloc写了半截错误检查,但核函数启动、cudaMemcpy、cudaFree这些步骤都没加错误判断——CUDA很多操作是异步的,出问题了不会主动报错,你得主动查,不然连哪一步崩了都不知道。

给你修正后的完整可运行代码

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <cuda.h>
#include <cuda_runtime.h>

#define N 10000000
#define MAX_ERR 1e-6

__global__ void write4(float *out, int n) {
    int index = threadIdx.x;
    int stride = blockDim.x;

    for(int i = index; i < n; i += stride){
        out[i] = 4.0;
    }
}

int main(){
    float *out, *d_out; 
    cudaError_t err;

    // 分配主机内存
    out = (float*)malloc(sizeof(float) * N);
    if (out == NULL) {
        fprintf(stderr, "主机内存分配失败!\n");
        return 1;
    }

    // 分配设备内存
    err = cudaMalloc((void**)&d_out, sizeof(float) * N);
    if(err != cudaSuccess){
        fprintf(stderr, "cudaMalloc 失败:%s\n", cudaGetErrorString(err));
        free(out);
        return 1;
    }

    // 启动核函数!这里用1个块,256个线程(常规配置)
    write4<<<1, 256>>>(d_out, N);
    // 检查核函数启动是否成功(核函数启动是异步的,必须用这个函数查)
    err = cudaGetLastError();
    if(err != cudaSuccess){
        fprintf(stderr, "核函数启动失败:%s\n", cudaGetErrorString(err));
        free(out);
        cudaFree(d_out);
        return 1;
    }
    // 等待GPU任务完成(拷贝前确保GPU干完活)
    cudaDeviceSynchronize();

    // 从设备拷贝回主机
    err = cudaMemcpy(out, d_out, sizeof(float) * N, cudaMemcpyDeviceToHost);
    if(err != cudaSuccess){
        fprintf(stderr, "cudaMemcpy 失败:%s\n", cudaGetErrorString(err));
        free(out);
        cudaFree(d_out);
        return 1;
    }

    // 验证结果(抽样检查,不用全遍历省时间)
    for(int i = 0; i < 10; i++){
        assert(fabs(out[i] - 4.0) < MAX_ERR);
    }
    // 检查中间位置
    assert(fabs(out[N/2] - 4.0) < MAX_ERR);
    // 检查末尾
    assert(fabs(out[N-1] - 4.0) < MAX_ERR);
    printf("所有抽样检查通过!CUDA环境正常工作~\n");

    // 释放内存
    free(out);
    cudaFree(d_out);

    return 0;
}

额外的环境验证小技巧

如果还是有问题,先跑CUDA自带的deviceQuery工具(一般在CUDA安装目录的samples文件夹里),它能直接告诉你GPU是否被正确识别,驱动和CUDA工具链版本是否匹配,这是快速排查环境问题的利器。

备注:内容来源于stack exchange,提问作者Gillespie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 11:04:51