CUDA内核指针参数变为空

CUDA内核指针参数变为空,cuda,cuda-gdb,Cuda,Cuda Gdb,我的CUDA内核需要很多数组,这些数组需要作为指向内核的指针传递。问题是,在内核启动之前,所有指针都有有效地址,而且cudamaloc和cudaMemcpy调用总是返回cudaSuccess,但一旦内核启动,所有这些参数都变为null 我对正在发生的事一无所知。这是我使用cuda gdb运行代码时得到的 CUDA Exception: Device Illegal Address The exception was triggered in device 0. Program received

我的CUDA内核需要很多数组,这些数组需要作为指向内核的指针传递。问题是,在内核启动之前,所有指针都有有效地址,而且
cudamaloc
cudaMemcpy
调用总是返回
cudaSuccess
,但一旦内核启动,所有这些参数都变为null

我对正在发生的事一无所知。这是我使用
cuda gdb运行代码时得到的

CUDA Exception: Device Illegal Address
The exception was triggered in device 0.

Program received signal CUDA_EXCEPTION_10, Device Illegal Address.
[Switching focus to CUDA kernel 0, grid 1, block (0,0,0), thread (64,0,0), device 0, sm 1, warp 2, lane 0]
0x00000000062a3dd8 in compute_data_and_match_kernel<<<(2,1,1),(512,1,1)>>> (a11=0x0, a12=0x0, a22=0x0, b1=0x0, b2=0x0, mask=0x0, wx=0x0, wy=0x0, du=0x0, dv=0x0, uu=0x0, 
    vv=0x0, Ix_c1=0x0, Ix_c2=0x0, Ix_c3=0x0, Iy_c1=0x0, Iy_c2=0x0, Iy_c3=0x0, Iz_c1=0x0, Iz_c2=0x0, Iz_c3=0x0, Ixx_c1=0x0, Ixx_c2=0x0, Ixx_c3=0x0, Ixy_c1=0x0, Ixy_c2=0x0, 
    Ixy_c3=0x0, Iyy_c1=0x0, Iyy_c2=0x0, Iyy_c3=0x0, Ixz_c1=0x0, Ixz_c2=0x0, Ixz_c3=0x0, Iyz_c1=0x0, Iyz_c2=0x0, Iyz_c3=0x0, desc_weight=0x0, desc_flow_x=0x0, 
    desc_flow_y=0x0, half_delta_over3=0.0833333358, half_beta=0, half_gamma_over3=0.833333313, width=59, height=26, stride=60) at opticalflow_aux.cu:441
441         ix_c1_val = Ix_c1[index]; iy_c1_val = Iy_c1[index]; iz_c1_val = Iz_c1[index];
(cuda-gdb) 
CUDA异常:设备地址非法
在设备0中触发了异常。
程序收到信号CUDA_异常_10,设备地址非法。
[将焦点切换到CUDA内核0、网格1、块(0,0,0)、线程(64,0,0)、设备0、sm 1、扭曲2、通道0]
计算数据和匹配内核中的0x00000000062a3dd8(a11=0x0,a12=0x0,a22=0x0,b1=0x0,b2=0x0,掩码=0x0,wx=0x0,wy=0x0,du=0x0,dv=0x0,uu=0x0,
vv=0x0,Ix_c1=0x0,Ix_c2=0x0,Iy_c1=0x0,Iy_c2=0x0,Iy_c3=0x0,Iz_c1=0x0,Iz_c2=0x0,Iz_c3=0x0,Ixx_c1=0x0,Ixx_c2=0x0,Ixx_c3=0x0,Ixy_c1=0x0,Ixy_c2=0x0,
Ixy_c3=0x0,Iyy_c1=0x0,Iyy_c2=0x0,Iyy_c3=0x0,Ixz_c1=0x0,Ixz_c3=0x0,Iyz_c1=0x0,Iyz_c2=0x0,Iyz_c3=0x0,描述权重=0x0,描述流量=0x0,
在光学流量辅助cu:441时,描述流量y=0x0,半三角形覆盖3=0.0833333358,半β=0,半伽马覆盖3=0.833333313,宽度=59,高度=26,步幅=60)
441 ix_c1_val=ix_c1[索引];iy_c1_val=iy_c1[索引];iz_c1_val=iz_c1[指数];
(cuda gdb)
有没有什么很明显的东西我遗漏了。 提前谢谢

编辑1: 正如Gilles所建议的,我正在尝试将主机指针和数据复制到一个结构中,然后再复制到设备上。为了简单起见(MCVE),我在struct中只使用了一个指针:

#include <cuda.h>
#include <stdio.h>

typedef struct test {
    float *ptr;
} test_t;

__global__ void test_kernel(test_t *s) {
    s->ptr[0] = s->ptr[1] = s->ptr[2] = s->ptr[3] = s->ptr[4] = 100;
    s->ptr[5] = s->ptr[6] = s->ptr[7] = s->ptr[8] = s->ptr[9] = 100;
}

int main() {

    float arr[] = {0,1,2,3,4,5,6,7,8,9};

    test_t *h_struct;
    h_struct = (test_t *)malloc(sizeof(test_t));
    h_struct->ptr = arr;

    test_t *d_struct;
    float *d_data;
    cudaMalloc((void **)&d_struct, sizeof(test_t));
    cudaMalloc((void **)&d_data, sizeof(float)*10);

    // Copy the data from host to device
    cudaMemcpy(d_data, h_struct->ptr, sizeof(float)*10,   cudaMemcpyHostToDevice);
    // Point the host struct ptr to device memory
    h_struct->ptr = d_data;
    // copy the host struct to device
    cudaMemcpy(d_struct, h_struct, sizeof(test_t), cudaMemcpyHostToDevice);


    // Kernel Launch
    test_kernel<<<1,1>>>(d_struct);
    // copy the device array to host
    cudaMemcpy(h_struct->ptr, d_data, sizeof(float)*10, cudaMemcpyDeviceToHost);

    cudaFree(d_data);
    cudaFree(d_struct);

    // Verifying if all the values have been set to 100
    int i;
    for(i=0 ; i<10 ; i++)
        printf("%f\t", h_struct->ptr[i]);

    return 0;
}
#包括
#包括
类型定义结构测试{
浮动*ptr;
}测试;
__全局无效测试内核(测试t*s){
s->ptr[0]=s->ptr[1]=s->ptr[2]=s->ptr[3]=s->ptr[4]=100;
s->ptr[5]=s->ptr[6]=s->ptr[7]=s->ptr[8]=s->ptr[9]=100;
}
int main(){
浮点arr[]={0,1,2,3,4,5,6,7,8,9};
测试t*h结构;
h_struct=(test_t*)malloc(sizeof(test_t));
h_结构->ptr=arr;
测试t*d结构;
浮点*d_数据;
cudamaloc((void**)和d_struct,sizeof(test_t));
Cudamaloc((void**)和d_数据,sizeof(float)*10;
//将数据从主机复制到设备
cudaMemcpy(d_数据,h_结构->ptr,sizeof(float)*10,cudaMemcpyHostToDevice);
//将主机结构ptr指向设备内存
h_结构->ptr=d_数据;
//将主机结构复制到设备
cudaMemcpy(d_结构、h_结构、sizeof(test_t)、cudaMemcpyHostToDevice);
//内核启动
测试内核(d_结构);
//将设备阵列复制到主机
cudaMemcpy(h_struct->ptr,d_数据,sizeof(float)*10,cudaMemcpyDeviceToHost);
cudaFree(d_数据);
cudaFree(d_结构);
//验证是否已将所有值设置为100
int i;
对于(i=0;iptr[i]);
返回0;
}

当我检查
d_struct->ptr
的值时,就在内核启动之前,它显示了
0x0
。(我已经在调试模式下使用nsight检查了这些值)

不确定这是否是问题所在,但我相信用于向内核传递参数的堆栈的大小是有限的。您可能需要创建一个存储参数的结构,将其复制到设备,并且只将指向它的指针作为参数传递给内核。然后,在内核中从结构中检索参数


编辑:添加已提交代码的更正版本。 这对我来说很有用,并且是我描述的原则的例证

#include <cuda.h>
#include <stdio.h>

typedef struct test {
    float *ptr;
} test_t;

__global__ void test_kernel(test_t *s) {
    s->ptr[0] = s->ptr[1] = s->ptr[2] = s->ptr[3] = s->ptr[4] = 100;
    s->ptr[5] = s->ptr[6] = s->ptr[7] = s->ptr[8] = s->ptr[9] = 100;
}

int main() {

    float arr[] = {0,1,2,3,4,5,6,7,8,9};

    test_t *h_struct;
    h_struct = (test_t *)malloc(sizeof(test_t));

    test_t *d_struct;
    float *d_data;
    cudaMalloc((void **)&d_struct, sizeof(test_t));
    cudaMalloc((void **)&d_data, sizeof(float)*10);

    // Copy the data from host to device
    cudaMemcpy(d_data, arr, sizeof(float)*10, cudaMemcpyHostToDevice);
    // Point the host struct ptr to device memory
    h_struct->ptr = d_data;
    // copy the host struct to device
    cudaMemcpy(d_struct, h_struct, sizeof(test_t), cudaMemcpyHostToDevice);

    // Kernel Launch
    test_kernel<<<1,1>>>(d_struct);
    // copy the device array to host
    cudaMemcpy(arr, d_data, sizeof(float)*10, cudaMemcpyDeviceToHost);

    cudaFree(d_data);
    cudaFree(d_struct);

    // Verifying if all the values have been set to 100
    int i;
    for(i=0 ; i<10 ; i++)
        printf("%f\t", arr[i]);

    return 0;
}
#包括
#包括
类型定义结构测试{
浮动*ptr;
}测试;
__全局无效测试内核(测试t*s){
s->ptr[0]=s->ptr[1]=s->ptr[2]=s->ptr[3]=s->ptr[4]=100;
s->ptr[5]=s->ptr[6]=s->ptr[7]=s->ptr[8]=s->ptr[9]=100;
}
int main(){
浮点arr[]={0,1,2,3,4,5,6,7,8,9};
测试t*h结构;
h_struct=(test_t*)malloc(sizeof(test_t));
测试t*d结构;
浮点*d_数据;
cudamaloc((void**)和d_struct,sizeof(test_t));
Cudamaloc((void**)和d_数据,sizeof(float)*10;
//将数据从主机复制到设备
cudaMemcpy(数据单位数据、arr、sizeof(float)*10,cudaMemcpyHostToDevice);
//将主机结构ptr指向设备内存
h_结构->ptr=d_数据;
//将主机结构复制到设备
cudaMemcpy(d_结构、h_结构、sizeof(test_t)、cudaMemcpyHostToDevice);
//内核启动
测试内核(d_结构);
//将设备阵列复制到主机
cudaMemcpy(arr,d_数据,sizeof(float)*10,cudaMemcpyDeviceToHost);
cudaFree(d_数据);
cudaFree(d_结构);
//验证是否已将所有值设置为100
int i;

对于(i=0;iI可以使用实际代码更新我的问题,如果需要的话,因为内核和内核启动的代码非常庞大。是的,请您始终提供一个,因此首先找到一个再现您的问题的最小示例,然后将其发布到此处您的新示例在内核运行后完全破坏了主机端数据处理。
h\u struct->ptr
不是有效的主机指针,您不能将其用作设备到主机内存传输的目标,也不能尝试打印其值。如果我修改您的代码,使
arr
用作内核后的目标,并打印出来,它将按预期工作并打印出100。可能您从未实际运行过此操作,因为如果如果是的话,你会得到一个主人segfault@talonmies感谢您指出这一点。它的工作原理与您所指出的一样。现在我将把它扩展到多个参数来处理我以前的场景。但是在内核启动之前,
d_struct->ptr
仍然被
0x0
检查并发现:显然,限制是256B@Giles是 啊甚至我也在看这个。让我修改我的代码并检查它。顺便说一句,不需要像我指出的线程中描述的那样初始化kenel,只需定义一个包含所有参数的结构即可