【问题标题】:C CUDA send struct array to host from deviceC CUDA 将结构数组从设备发送到主机
【发布时间】:2018-03-13 06:30:30
【问题描述】:

我有这个结构

struct Data {
    int x
    int y;
    float z;
};

我发送给内核没有问题

__global__ void calculate(Data *d_data) {
    d_data[myCounter].x = 1;
    d_data[myCounter].y = 1;
    d_data[myCounter].z = 1.0;
}

#DEFINE MAX_SIZE 100

int main() {
  Data * data = (Data *)malloc(MAX_SIZE * sizeof(Data));
  Data *d_data;

  const int DATA_BYTES = MAX_SIZE * sizeof(Data);
  int elements = 20;

  cudaError_t cudaStatus;

  cudaStatus = cudaMalloc((void **)&d_data, DATA_BYTES);
  if (cudaStatus != cudaSuccess) {
    fprintf(stderr, "cudaMalloc failed!");
  }

  cudaStatus = cudaMemcpy(d_data, data, DATA_BYTES, cudaMemcpyHostToDevice);
  if (cudaStatus != cudaSuccess) {
    fprintf(stderr, "cudaMemcpy failed!");
  }

  calculate << < 1, elements >> > (d_data);

  cudaMemcpy(data, d_data, DATA_BYTES, cudaMemcpyDeviceToHost);
  if (cudaStatus != cudaSuccess) {
    fprintf(stderr, "cudaMemcpy failed!");
  }

  cudaDeviceSynchronize();

  for (i = 0; i < elements; i++) {
    printf("%2d %2.1f %s\n", d_data[i].x, d_data[i].y, 
    d_data[i].z);    // this prints nothing
  }
  cudaStatus = cudaDeviceReset();

}

当我在内核函数中测试 struct array 计算时,它打印出正确的结果,但是当我尝试使用 cudaMemcpy 程序从设备发送数据到主机时,程序崩溃,没有错误并且什么也不打印,我如何从设备传输这个 struct array?

【问题讨论】:

  • 您能否在上面的代码中提供一些有关myCounter 值的详细信息?另外,您能否提供您用于此代码的编译方案?实际上,结构对齐可能会有所不同。最后,您要在执行cudaDeviceSynchronize 时检查错误。

标签: c struct cuda


【解决方案1】:

您显示的代码有几个问题。

  1. 您的结构定义中缺少分号。
  2. 内核代码中没有为变量myCounter提供定义
  3. 没有为main 中的变量i 提供定义
  4. 您正试图从设备变量d_data 而不是主机变量data 进行打印。这在 CUDA 中是非法的。复制到宿主变量data 后,从那里打印。
  5. 您使用了不正确的printf 格式说明符。结构中的数据类型是intintfloat。您使用的 %2d %2.1f %s 将匹配 intfloat 和字符串变量(以 null 结尾的字符数组),但对于您的结构不正确。

以下代码解决了上述问题,并且对我来说似乎可以正常运行:

$ cat t430.cu
#include <stdio.h>

struct Data {
    int x;  // was missing semicolon
    int y;
    float z;
};

__global__ void calculate(Data *d_data) {
    int myCounter = threadIdx.x;  // this line was missing
    d_data[myCounter].x = 1;
    d_data[myCounter].y = 1;
    d_data[myCounter].z = 1.0;
}

#define MAX_SIZE 100

int main() {
  Data * data = (Data *)malloc(MAX_SIZE * sizeof(Data));
  Data *d_data;
  int i;   // this line was missing
  const int DATA_BYTES = MAX_SIZE * sizeof(Data);
  int elements = 20;

  cudaError_t cudaStatus;

  cudaStatus = cudaMalloc((void **)&d_data, DATA_BYTES);
  if (cudaStatus != cudaSuccess) {
    fprintf(stderr, "cudaMalloc failed!");
  }

  cudaStatus = cudaMemcpy(d_data, data, DATA_BYTES, cudaMemcpyHostToDevice);
  if (cudaStatus != cudaSuccess) {
    fprintf(stderr, "cudaMemcpy failed!");
  }

  calculate << < 1, elements >> > (d_data);

  cudaMemcpy(data, d_data, DATA_BYTES, cudaMemcpyDeviceToHost);
  if (cudaStatus != cudaSuccess) {
    fprintf(stderr, "cudaMemcpy failed!");
  }

  cudaDeviceSynchronize();

  for (i = 0; i < elements; i++) {
    printf("%2d %2d %2.1f\n", data[i].x, data[i].y,
    data[i].z);    // this was trying to print from d_data
  }
  cudaStatus = cudaDeviceReset();

}
$ nvcc -arch=sm_61 -o t430 t430.cu
$ cuda-memcheck ./t430
========= CUDA-MEMCHECK
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
 1  1 1.0
========= ERROR SUMMARY: 0 errors
$

【讨论】:

    【解决方案2】:

    您应该将此宏添加到您的代码中

    #define CUDA_SAFE_CALL(call)                                               
    do {                                                                  
        cudaError_t err = call;                                           
        if (cudaSuccess != err) {                                         
            fprintf (stderr, "Cuda error in file '%s' in line %i : %s.", 
                     __FILE__, __LINE__, cudaGetErrorString(err) );       
            exit(EXIT_FAILURE);                                          
        }                                                                
    } while (0)
    

    然后:

    CUDA_SAFE_CALL(cudaMemcpy(data, d_data, DATA_BYTES, cudaMemcpyDeviceToHost));
    cudaDeviceSynchronize();
    

    顺便说一句,您的myCounter 似乎不对。您能否提供一些关于上面代码中 myCounter 值的详细信息?

    【讨论】:

    • 您应该在 cudaDeviceSynchronize 上添加错误检查。
    猜你喜欢
    • 2017-08-27
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 2013-04-04
    • 2016-03-24
    • 2018-03-15
    • 1970-01-01
    • 2014-08-29
    相关资源
    最近更新 更多