У меня возникают проблемы с копированием данных с моего устройства обратно на хост. Мои данные организованы в структурах:Неверная ошибка аргумента при копировании данных с устройства на хост
typedef struct Array2D {
double* arr;
int rows;
int cols;
} Array2D;
arr
является «плоским» массивом. rows
и cols
описывает размеры.
Приведенный ниже код показывает, как я пытаюсь скопировать данные обратно на хост:
h_output = (Array2D*) malloc(sizeof(Array2D));
cudaMemcpy(h_output, d_output, sizeof(Array2D), cudaMemcpyDeviceToHost);
double* h_arr = (double*) malloc(h_output->cols*h_output->rows*sizeof(double));
cudaMemcpy(h_arr, h_output->arr, h_output->cols*h_output->rows*sizeof(double), cudaMemcpyDeviceToHost);
h_output->arr = h_arr;
Однако, в четвертой строке выполнение терпит неудачу с ошибкой Cuda 11 (неверный аргумент). Я не понимаю, почему это происходит. Размер массива правильный, и я могу получить доступ к h_output
и h_array
от хоста, и оба имеют «реальные» адреса.
EDIT Извините за поздний ответ на запрос о предоставлении дополнительной информации (= больше кода).
Я тестировал, что указатель d_output->arr
является указателем устройства, пытаясь получить доступ к значению указателя устройства на хосте. Как и ожидалось, мне не разрешили это сделать, оставив меня с мыслью, что d_output->arr
на самом деле является допустимым указателем на устройство.
Целью этого кода является решение дифференциального уравнения Тиле с использованием метода Рунге-Кутты четвертого порядка.
class CalculationSpecification
{
/* FUNCTIONS OMITTED */
public:
__device__ void RK4_n(CalculationSpecification* cs, CalcData data, Array2D* d_output)
{
double* rk4data = (double*)malloc((data.pdata->endYear - data.pdata->startYear + 1)*data.pdata->states*sizeof(double));
/* CALCULATION STUFF HAPPENS HERE */
// We know that rows = 51, cols = 1 and that rk4data contains 51 values as it should.
// This was confirmed by using printf directly in this function.
d_output->arr = rk4data;
d_output->rows = data.pdata->endYear - data.pdata->startYear + 1;
d_output->cols = data.pdata->states;
}
};
class PureEndowment : CalculationSpecification
{
/* FUNCTIONS OMITTED */
public:
__device__ void Compute(Array2D *result, CalcData data)
{
RK4_n(this, data, result);
}
};
__global__ void kernel2(Array2D *d_output)
{
/* Other code that initializes 'cd'. */
PureEndowment pe;
pe.Compute(d_output,cd);
}
void prepareOutputSet(Array2D* h_output, Array2D* d_output, int count)
{
h_output = (Array2D*) malloc(sizeof(Array2D));
cudaMemcpy(h_output, d_output, sizeof(Array2D), cudaMemcpyDeviceToHost); // After this call I can read the correct values of row, col as well as the address of the pointer.
double* h_arr = (double*) malloc(h_output->cols*h_output->rows*sizeof(double));
cudaMemcpy(h_arr, h_output->arr, h_output->cols*h_output->rows*sizeof(double), cudaMemcpyDeviceToHost)
h_output->arr = h_arr;
}
int main()
{
Array2D *h_output, *d_output;
cudaMalloc((void**)&d_output, sizeof(Array2D));
kernel2<<<1,1>>>(d_output);
cudaDeviceSynchronize();
prepareOutputSet(h_output, d_output, 1);
getchar();
return 0;
}
EDIT2
Кроме того, я теперь протестированы, что значение d_output->arr
при запуске на устройстве идентично значению h_output->arr
после первого cudaMemcpy
-Call в prepareOutputSet
.
Наиболее вероятным источником ошибки является 'houtput-> arr', не являющийся допустимым указателем устройства. Можете ли вы немного расширить свой код, чтобы показать, как вы распределяете и копируете содержимое 'd_output' на устройство? – talonmies
'd_output' и его содержимое выделяется на устройстве с помощью' malloc() '. Я уверен, что он содержит фактические данные, поскольку я пытался распечатать содержимое 'd_output-> arr' и получил ожидаемый результат. – ssnielsen
Вы имеете в виду 'h_output' _and its contents_? Потому что 'd_output' не отображается в вашем примере кода. – pQB