Недопустимый аргумент CUDA при попытке скопировать структуру в память устройства (cudaMemcpy)

#c #c #cuda

#c #c #cuda

Вопрос:

Я пытаюсь выяснить, как я должен создать структуру / класс, предназначенный для отправки на устройство, но я продолжаю получать эту ошибку CUDA с «недопустимым аргументом». Я привел небольшой пример, показывающий ошибку:

 #include <iostream>
#include <cstdio>
using namespace std;

#define CUDA_WARN(XXX) 
    do { if (XXX != cudaSuccess) cerr << "CUDA Error: " << 
        cudaGetErrorString(XXX) << ", at line " << __LINE__ 
        << endl; cudaDeviceSynchronize(); } while (0)

struct P {
    double x,y;
    __host__ __device__ void init(const double amp;a, const double amp;b) {
        x = a; y = b; }
};

int main(int argc, char **argv)
{
    P hP, hQ, dP;
    cout << "Size of P: " << sizeof(P) << endl;
    CUDA_WARN(cudaMalloc((void**) amp;dP, sizeof(P)));
    printf("dP: %pn", amp;dP); // print dP's address on the device
    hP.init(1.2,-2.1);
    hQ.init(0.,0.);
    CUDA_WARN(cudaMemcpy(amp;dP, amp;hP, sizeof(P), cudaMemcpyHostToDevice));
    CUDA_WARN(cudaMemcpy(amp;hQ, amp;dP, sizeof(P), cudaMemcpyDeviceToHost));
    cout << "Copy back: " << hQ.x << "t" << hQ.y << endl;
    dP.init(3.,3.);
    CUDA_WARN(cudaMemcpy(amp;hP, amp;dP, sizeof(P), cudaMemcpyDeviceToHost));
    cout << "Copy new:  " << hP.x << "t" << hP.y << endl;
    return 0;
}
 

Я компилирую с помощью (моя карта — Tesla C2050):

 nvcc -arch sm_20 -o exec file.cu
 

Результат, который я получаю,:

 Size of P: 16
dP: 0x7fff82d4b7b0
CUDA Error: invalid argument, at line 24
CUDA Error: invalid argument, at line 25
Copy back: 0    0
CUDA Error: invalid argument, at line 28
Copy new:  1.2  -2.1


------------------
(program exited with code: 0)
Press return to continue
 

Спасибо, ребята, если вы могли бы мне помочь в этом!

====== После комментариев @talonmies, @JackOLantern, @Robert Crovella =======

Спасибо, ребята! Вы действительно помогли! Основываясь на комментариях, я смог исправить свой код, и теперь он работает. Просто для регистрации окончательного решения:

 #include <iostream>
#include <cstdio>
using namespace std;

#define CUDA_WARN(XXX) 
    do { if (XXX != cudaSuccess) cerr << "CUDA Error: " << 
        cudaGetErrorString(XXX) << ", at line " << __LINE__ 
        << endl; cudaDeviceSynchronize(); } while (0)

struct P {
    double x,y;
    __host__ __device__ void init(const double amp;a, const double amp;b) {
        x = a; y = b; }
};

/* INCLUDED KERNEL FUNCTION */
__global__ void dev_P_init(P *p, double a, double b) {
    p->init(a,b);
}

int main(int argc, char **argv)
{
    P hP, hQ, *dP; //*changed*
    cout << "Size of P: " << sizeof(P) << endl;
    CUDA_WARN(cudaMalloc((void**) amp;dP, sizeof(P)));
    printf("dP: %pn", amp;dP); // print dP's address on the device
    hP.init(1.2,-2.1);
    hQ.init(0.,0.);
    CUDA_WARN(cudaMemcpy(dP, amp;hP, sizeof(P), cudaMemcpyHostToDevice)); //*changed*
    CUDA_WARN(cudaMemcpy(amp;hQ, dP, sizeof(P), cudaMemcpyDeviceToHost)); //*changed*
    cout << "Copy back: " << hQ.x << "t" << hQ.y << endl;
    dev_P_init<<< 1, 1 >>>(dP,3., 3.); //*call to kernel*
    CUDA_WARN(cudaMemcpy(amp;hP, dP, sizeof(P), cudaMemcpyDeviceToHost)); //*changed*
    cout << "Copy new:  " << hP.x << "t" << hP.y << endl;
    return 0;
}
 

И исправленный вывод:

 Size of P: 16
dP: 0x7fff6fa2e498
Copy back: 1.2  -2.1
Copy new:  3    3


------------------
(program exited with code: 0)
Press return to continue
 

Комментарии:

1. Я считаю, что вам нужно выделить память на графическом процессоре, а затем скопировать структуру туда, вы не можете просто так использовать память стека хоста

2. amp;dp недопустимый указатель устройства. Это источник ошибки.

3. Ответ, данный @JackOLantern, правильный. Как только вы исправите указанные там проблемы, ваш dP.init() (или, dP->init() ) также не будет делать то, что вы ожидаете от него в коде хоста. Я ожидаю, что это ошибка seg. Если вы хотите / намереваетесь запустить код устройства, вы должны запустить ядро.

Ответ №1:

Как уже заметил @talonmies, amp;dP недопустимый указатель устройства. Действительно, dP это переменная, которая находится на хосте, поэтому ее адрес указывает на пространство памяти хоста. Напротив, when dP является указателем, cudaMalloc получит свое значение в качестве параметра, а его значение будет указывать на область памяти устройства.

Это правильная версия вашего кода:

 #include <iostream>
#include <cstdio>
using namespace std;

#define CUDA_WARN(XXX) 
    do { if (XXX != cudaSuccess) cerr << "CUDA Error: " << 
    cudaGetErrorString(XXX) << ", at line " << __LINE__ 
    << endl; cudaDeviceSynchronize(); } while (0)

struct P {
    double x,y;
    __host__ __device__ void init(const double amp;a, const double amp;b) {
    x = a; y = b; }
};

int main(int argc, char **argv)
{
    P *dP;
    P hP, hQ;
    CUDA_WARN(cudaMalloc((void**) amp;dP, sizeof(P)));
    CUDA_WARN(cudaMemcpy(dP, amp;hP, sizeof(P), cudaMemcpyHostToDevice));
    CUDA_WARN(cudaMemcpy(amp;hQ, dP, sizeof(P), cudaMemcpyDeviceToHost));
    CUDA_WARN(cudaMemcpy(amp;hP, dP, sizeof(P), cudaMemcpyDeviceToHost));

    return 0;
}