CUDA中结构的简单操作:分段故障

CUDA中结构的简单操作:分段故障,cuda,Cuda,这是我第一次在CUDA中实现结构。在下面的程序中,我将结构复制到GPU,并对数据执行基本操作,然后将结果复制回主机 #include<stdio.h> inline cudaError_t checkCuda(cudaError_t result) { #if defined(DEBUG) || defined(_DEBUG) if (result != cudaSuccess) { fprintf(stderr, "CUDA Run

这是我第一次在CUDA中实现结构。在下面的程序中,我将结构复制到GPU,并对数据执行基本操作,然后将结果复制回主机

#include<stdio.h>

inline cudaError_t checkCuda(cudaError_t result)
{
    #if defined(DEBUG) || defined(_DEBUG)
        if (result != cudaSuccess) {
            fprintf(stderr, "CUDA Runtime Error: %sn", cudaGetErrorString(result));
        assert(result == cudaSuccess);
        }
    #endif
    return result;
}

typedef struct myStruct {
    int* a;
    int b;
}MyStruct;

__global__ void structOperation(MyStruct *d_data){
    int idx = threadIdx.x;

    d_data->a[idx] += 10;
}

int main(){
    MyStruct *h_data, *d_data, *out_data;

    size_t structSize = sizeof(MyStruct);
    size_t intSize = sizeof(int);


    h_data = (MyStruct *) malloc(structSize * 1);
    h_data->b = 32;
    h_data->a = (int *)malloc(intSize * h_data->b);

    out_data = (MyStruct *) malloc(structSize * 1);
    out_data->b = 32;
    out_data->a = (int *)malloc(intSize * out_data->b);

    for(int i = 0; i<32; i++){
        h_data->a[i] = i;   
    }

    //Memory allocation for the Struct
    checkCuda(cudaMalloc(&d_data, sizeof(MyStruct) * 1));
    checkCuda(cudaMalloc(&(d_data->a), sizeof(int) * 32));


    checkCuda(cudaMemcpy(&d_data, &h_data, sizeof(MyStruct) * 1, cudaMemcpyHostToDevice));
    checkCuda(cudaMemcpy(&(d_data->a), &(h_data->a), sizeof(int) * 32, cudaMemcpyHostToDevice)); 


    structOperation<<<1,32>>>(d_data);


    checkCuda(cudaMemcpy(&out_data, &d_data, sizeof(myStruct) * 1, cudaMemcpyDeviceToHost));
  //cudaMemcpy(&(out_data->a), &(d_data->a), sizeof(int) * d_data->b, cudaMemcpyDeviceToHost); 

    printf("\nDataElements : ");
    for(int i = 0; i<32; i++){
        printf("    %d",out_data->a[i]);
    }
    printf("\n");
}
#包括
内联cudaError\u t checkCuda(cudaError\u t结果)
{
#如果已定义(调试)| |已定义(_调试)
如果(结果!=cudaSuccess){
fprintf(stderr,“CUDA运行时错误:%sn”,cudaGetErrorString(结果));
断言(结果==cudaSuccess);
}
#恩迪夫
返回结果;
}
typedef结构myStruct{
int*a;
int b;
}我的结构;
__全局无效结构操作(MyStruct*d_数据){
int idx=threadIdx.x;
d_数据->a[idx]+=10;
}
int main(){
MyStruct*h_数据、*d_数据、*out_数据;
size\u t structSize=sizeof(MyStruct);
size\u t intSize=sizeof(int);
h_data=(MyStruct*)malloc(structSize*1);
h_数据->b=32;
h_数据->a=(int*)malloc(intSize*h_数据->b);
out_data=(MyStruct*)malloc(structSize*1);
输出数据->b=32;
out\u data->a=(int*)malloc(intSize*out\u data->b);
对于(int i=0;ia[i]=i;
}
//结构的内存分配
检查CUDA(cudaMalloc(&d_数据,sizeof(MyStruct)*1);
检查CUDA(cudaMalloc(&(d_数据->a),sizeof(int)*32);
检查CUDA(cudaMemcpy(&d_数据,&h_数据,sizeof(MyStruct)*1,cudaMemcpyHostToDevice));
选中CUDA(cudaMemcpy(&(d_数据->a),&(h_数据->a),sizeof(int)*32,cudaMemcpyHostToDevice));
结构操作(d_数据);
选中CUDA(cudaMemcpy(&out_数据,&d_数据,sizeof(myStruct)*1,cudaMemcpyDeviceToHost));
//CUDAMCPY(&(out_数据->a),&(d_数据->a),sizeof(int)*d_数据->b,CUDAMCPydeviceToHost);
printf(“\n数据元素:”);
对于(int i=0;ia[i]);
}
printf(“\n”);
}

由于执行,我得到了“分段错误”。我猜我操作的结构不正确。正确的实现方法是什么?

提供的代码中有几个无效的内存访问

  • 从主机(如
    d_data->a
    访问设备内存(使用
    cudamaloc
    分配)将导致未定义的行为(分段故障等)
  • cudaMemcpy
    将指针作为参数,而不是指针的地址。因此
    cudaMemcpy(&d\u数据,&h\u数据…
    应替换为
    cudaMemcpy(d\u数据,h\u数据…
  • 将设备指针作为成员分配给设备对象有点棘手。可以通过以下方式实现:

  • 分配一个临时主机对象(
    MyStruct temp
  • 将设备内存分配给设备上所需的成员(
    cudamaloc(&temp.a,bytes)
  • 分配设备对象(
    cudamaloc(&d_数据,sizeof(MyStruct)
  • 将临时主机对象复制到设备对象(
    cudaMemcpy(d_数据,&temp,sizeof(MyStruct),cudaMemcpyHostToDevice)
  • 请记住,当您在设备上修改
    d_data->a
    的内容时,
    temp.a
    也会被修改,因为它们实际上指向设备上的相同内存位置

    最终的主要功能如下所示:

    int main(){
        MyStruct *h_data, *d_data, *out_data;
    
        size_t structSize = sizeof(MyStruct);
        size_t intSize = sizeof(int);
    
    
        h_data = (MyStruct *) malloc(structSize * 1);
        h_data->b = 32;
        h_data->a = (int *)malloc(intSize * h_data->b);
    
        out_data = (MyStruct *) malloc(structSize * 1);
        out_data->b = 32;
        out_data->a = (int *)malloc(intSize * out_data->b);
    
        for(int i = 0; i<32; i++){
            h_data->a[i] = i;   
        }
    
        //Create temporary MyStruct object on host and allocate memory to its member "a" on device
        MyStruct temp;
        temp.b = h_data->b;
        checkCuda(cudaMalloc(&temp.a, 32 * sizeof(int)));
    
        //Copy host data to temp.a
        checkCuda(cudaMemcpy(temp.a, h_data->a, 32 * sizeof(int), cudaMemcpyHostToDevice));
    
        //Memory allocation for the device MyStruct
        checkCuda(cudaMalloc(&d_data, sizeof(MyStruct) * 1));
        //Copy actual object to device
        checkCuda(cudaMemcpy(d_data, &temp, sizeof(MyStruct) * 1, cudaMemcpyHostToDevice));
    
    
        structOperation<<<1,32>>>(d_data);
    
        //temp.a will be updated after kernel launch
        checkCuda(cudaMemcpy(out_data->a, temp.a, 32 * sizeof(int), cudaMemcpyDeviceToHost)); 
    
        printf("\nDataElements : ");
        for(int i = 0; i<32; i++)
        {
            printf("    %d",out_data->a[i]);
        }
        printf("\n");
    
        checkCuda(cudaFree(temp.a));
        checkCuda(cudaFree(d_data));
    
        free(h_data->a);
        free(out_data->a);
        free(h_data); 
        free(out_data);
    }
    
    intmain(){
    MyStruct*h_数据、*d_数据、*out_数据;
    size\u t structSize=sizeof(MyStruct);
    size\u t intSize=sizeof(int);
    h_data=(MyStruct*)malloc(structSize*1);
    h_数据->b=32;
    h_数据->a=(int*)malloc(intSize*h_数据->b);
    out_data=(MyStruct*)malloc(structSize*1);
    输出数据->b=32;
    out\u data->a=(int*)malloc(intSize*out\u data->b);
    对于(int i=0;ia[i]=i;
    }
    //在主机上创建临时MyStruct对象,并将内存分配给设备上的成员“a”
    我的结构温度;
    温度b=h_数据->b;
    检查CUDA(cudaMalloc(&temp.a,32*sizeof(int));
    //将主机数据复制到临时a
    选中CUDA(cudaMemcpy(温度a,h_数据->a,32*sizeof(int),cudaMemcpyHostToDevice));
    //设备MyStruct的内存分配
    检查CUDA(cudaMalloc(&d_数据,sizeof(MyStruct)*1);
    //将实际对象复制到设备
    检查CUDA(cudaMemcpy(数据、温度和大小(MyStruct)*1,cudaMemcpyHostToDevice));
    结构操作(d_数据);
    //temp.a将在内核启动后更新
    选中CUDA(cudaMemcpy(输出数据->a,温度a,32*sizeof(int),cudaMemcpyDeviceToHost));
    printf(“\n数据元素:”);
    对于(int i=0;ia[i]);
    }
    printf(“\n”);
    检查CUDA(cudaFree(临时a));
    检查CUDA(cudaFree(d_数据));
    免费(h_数据->a);
    自由(输出数据->a);
    免费(h_数据);
    免费(out_数据);
    }
    
    用于查找哪个CUDA呼叫failed@m.s.添加了cudaError检查。这实际上是一些我无法理解的内存冲突问题。仍然会给我分段错误。什么错误消息?在哪行?您的问题可能会被标记为重复。请参阅和。当您执行此操作时,您正在从主机访问设备内存是:
    &(d_data->a)
    中的
    cudamaloc
    cudaMemcpy
    调用。现在这就提出了几个问题。1.结构对象的成员(此处为temp)如何在设备内存中声明其内存,尽管对象在主机内存中声明?它甚至不是指向结构对象的指针,而是实际的结构对象。2.为什么我们不能直接执行从主机到设备的结构复制,只执行h_数据和d_数据之间的数据传输,而不使用temp?@sandeep.ganage的成员主机对象只是一个简单的指针。当我们分配设备内存时,指针本身驻留在主机上,但它所指向的内存区域存在于设备上。要将设备内存分配给没有构造函数的结构的成员,结构对象应该驻留在主机上,否则我们如何访问其成员对于分配?结构类型(指针或对象)与其成员的显式内存分配无关。@sandeep.ganage….分配设备内存(u