c++ - cudaMemcpy 不起作用

标签 c++ cuda

在下面的代码中,cudaMemcpy 不工作,它返回一个错误,然后程序退出。可能是什么问题?在我看来我没有做违法的事情, vector 的大小对我来说似乎没问题。

算法可能在某些时候做错了,但我想这个想法是正确的。代码是通过并行地做一些部分求和来对 n 个数字求和,然后重新迭代。

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>
#include <iostream>

__device__ int aug_vec(int *vec, const int& i, const int& size) {
    return (i >= size) ? 0 : vec[i];
}

__global__ void sumVectorElements(int *vec,const int& size) {
    const int i = (blockDim.x*blockIdx.x + threadIdx.x);
    vec[i] = aug_vec(vec, 2*i, size) + aug_vec(vec, 2 * i + 1, size);
}

__host__ int parallel_sum(int *vec,const int& size) {

    cudaError_t err;
    int *d_vec, *cp_vec;
    int n_threads = (size >> 1) + (size & 1);

    cp_vec = new int[size];
    err = cudaMalloc((void**)&d_vec, size * sizeof(int));

    if (err != cudaSuccess) {
        std::cout << "error in cudaMalloc!" << std::endl;
        exit(1);
    }

    err = cudaMemcpy(d_vec, vec, size*sizeof(int), cudaMemcpyHostToDevice);

    if (err != cudaSuccess) {
        std::cout << "error in cudaMemcpy!" << std::endl;
        exit(1);
    }

    int curr_size = size;
    while (curr_size > 1) {
        std::cout << "size = " << curr_size << std::endl;
        sumVectorElements<<<1,n_threads>>>(d_vec, curr_size);
        curr_size = (curr_size >> 1) + (curr_size & 1);
    }

    err = cudaMemcpy(cp_vec, d_vec, size*sizeof(int), cudaMemcpyDeviceToHost); //THIS LINE IS THE PROBLEM!

    if (err != cudaSuccess) {
        std::cout << "error in cudaMemcpy" << std::endl;
        exit(1);
    }

    err = cudaFree(d_vec);

    if (err != cudaSuccess) {
        std::cout << "error in cudaFree" << std::endl;
        exit(1);
    }

    int rval = cp_vec[0];

    delete[] cp_vec;

    return rval;
}

int main(int argc, char **argv) {
    const int n_blocks = 1;
    const int n_threads_per_block = 12;

    int vec[12] = { 0 };
    for (auto i = 0; i < n_threads_per_block; ++i) vec[i] = i + 1;
    int sum = parallel_sum(vec, n_threads_per_block);
    std::cout << "Sum = " << sum << std::endl;

    system("pause");

    return 0;
}

最佳答案

kernel之后的cudaMemcpy操作实际上是异步报错,这是由于kernel执行造成的。您的错误报告是原始的。如果您有错误代码,您可以通过打印出将该错误代码传递给 cudaGetErrorString() 的结果来获得更多有用的信息。

由于使用了引用参数,内核中发生错误:

__global__ void sumVectorElements(int *vec,const int& size) {
                                           ^^^^^^^^^^^^^^^

您传递给内核并期望在内核代码中可用的任何参数必须引用按值传递的数据,或者可以从设备代码访问/引用的数据。例如,将主机指针传递给设备代码在 CUDA 中通常是不合法的,因为在设备代码中取消引用主机指针的尝试将会失败。

上述异常(exception)情况是可在设备代码中访问的数据/指针/引用。 Unified memorypinned/mapped data是两个示例,此处均未使用。

因此,引用参数涉及主机内存中项目 (size) 的引用(基本上是地址)。当内核代码试图使用这个项目时,它必须首先取消引用它。在设备代码中取消引用主机项在 CUDA 中是非法的(除非使用 UM 或固定内存)。

这种情况下的解决方案很简单:转换为普通的按值传递情况:

__global__ void sumVectorElements(int *vec,const int size) ...
                                                    ^
                                                 remove ampersand

关于c++ - cudaMemcpy 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49353187/

相关文章:

c++ - 默认构造函数

c++ - 如何在滚动区动态插入项目并在Qt中加载滚动条?

c++ - C++ 初级多项式程序

c++ - 在不同的编译器上转换为void **

visual-studio - 在 Visual Studio 2013 中为 CUDA 7.0 启用语法高亮

cuda - 为什么 cudaPointerGetAttributes() 返回主机指针的无效参数?

cuda - 在 CUDA 中读取 nvprof 的输出

cuda - 在 Nsight Compute 中解释计算工作负载分析

c++按时间和日期自动递增构建版本

c++ - 遇到换行时 getline 崩溃