【问题标题】:Implementing CUDA VecAdd from sample code从示例代码实现 CUDA VecAdd
【发布时间】:2012-11-10 07:04:55
【问题描述】:

我正在尝试测试来自 CUDA 站点 http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#kernels 的示例代码。

我只想添加两个大小为 4 的数组 A 和 B,并将其存储在数组 C 中。这是我目前所拥有的:

#include <stdio.h>
#include "util.h"
void print_array(int* array, int size) {
int i;
for (i = 0; i < size; i++) {
    printf("%d ", array[i]);
}
printf("\n");
}

__global__ void VecAdd(int* A, int* B, int* C) {
int i = threadIdx.x;
C[i] = A[i] + B[i];
}

int main(int argc , char **argv) {
int N = 4;
    int i;
int *A = (int *) malloc(N * sizeof(int));
int *B = (int *) malloc(N * sizeof(int));
int *C = (int *) malloc(N * sizeof(int));

for (i = 0; i < N; i++) {
    A[i] = i + 1;
    B[i] = i + 1;
}

print_array(A, N);
print_array(B, N);


VecAdd<<<1, N>>>(A, B, C);
print_array(C, N);
    return 0;
}

我希望 C 数组(输出的最后一行)为 2、4、6、8,但似乎没有添加:

1 2 3 4
1 2 3 4
0 0 0 0

我错过了什么?

【问题讨论】:

    标签: arrays c parallel-processing cuda gpu


    【解决方案1】:

    首先,您必须定义指针,以保存将复制到 GPU 的数据:

    在您的示例中,我们希望将数组“a”、“b”和“c”从 CPU 复制到 GPU's 全局内存。

    int a[array_size], b[array_size],c[array_size]; // your original arrays
    int *a_cuda,*b_cuda,*c_cuda;                    // defining the "cuda" pointers 
    

    定义每个数组将占用的大小。

    int size = array_size * sizeof(int); // Is the same for the 3 arrays
    

    然后将空间分配给将在 cuda 中使用的数据:

    Cuda 内存分配

    msg_erro[0] = cudaMalloc((void **)&a_cuda,size);
    msg_erro[1] = cudaMalloc((void **)&b_cuda,size);
    msg_erro[2] = cudaMalloc((void **)&c_cuda,size);
    

    现在我们需要将这些数据从 CPU 复制到 GPU:

    从 CPU 复制到 GPU

    msg_erro[3] = cudaMemcpy(a_cuda, a,size,cudaMemcpyHostToDevice);
    msg_erro[4] = cudaMemcpy(b_cuda, b,size,cudaMemcpyHostToDevice);
    msg_erro[5] = cudaMemcpy(c_cuda, c,size,cudaMemcpyHostToDevice);
    

    执行内核

    int blocks = //;
    int threads_per_block = //;
    VecAdd<<<blocks, threads_per_block>>>(a_cuda, b_cuda, c_cuda);
    

    将结果从 GPU 复制到 CPU(在我们的示例数组 C 中):

    msg_erro[6] = cudaMemcpy(c,c_cuda,size,cudaMemcpyDeviceToHost);
    

    可用内存:

    cudaFree(a_cuda);
    cudaFree(b_cuda);
    cudaFree(c_cuda);
    

    出于调试目的,我通常将函数的状态保存在数组中,如下所示:

    cudaError_t msg_erro[var];
    

    但是,这并不是绝对必要的,但如果在分配或内存转移过程中发生错误,它会节省您的时间。如果您愿意,可以从上面的代码中取出所有的 'msg_erro[x] ='。

    如果您保留 'msg_erro[x] =',并且如果确实发生错误,您可以使用如下函数来打印这些错误:

    void printErros(cudaError_t *erros,int size)
    {
     for(int i = 0; i < size; i++)
          printf("{%d} => %s\n",i ,cudaGetErrorString(erros[i]));
    }
    

    【讨论】:

      【解决方案2】:

      您需要在 GPU 之间来回传输内存,例如

          int *a_GPU, *b_GPU, *c_GPU;
              
          cudaMalloc(&a_GPU, N*sizeof(int));
          cudaMalloc(&b_GPU, N*sizeof(int));
          cudaMalloc(&c_GPU, N*sizeof(int));
              
          cudaMemcpy(a_GPU, A, N*sizeof(int), cudaMemcpyHostToDevice);
          cudaMemcpy(b_GPU, B, N*sizeof(int), cudaMemcpyHostToDevice);
      
          VecAdd<<<1, N>>>(a_GPU, b_GPU, c_GPU);
      
          cudaMemcpy(C, c_GPU, N*sizeof(int), cudaMemcpyDeviceToHost);
              
          print_array(C, N);
      
          cudaFree(a_GPU);
          cudaFree(b_GPU);
          cudaFree(c_GPU);
      

      【讨论】:

      • 这是正确的除了内核调用它仍在使用主机指针
      猜你喜欢
      • 2012-02-28
      • 2017-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      • 1970-01-01
      • 2011-09-19
      • 1970-01-01
      相关资源
      最近更新 更多