У меня проблемы с копированием данных с моего устройства обратно на хост.Мои данные организованы в виде структуры:
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
с хоста, и у обоих есть «реальные» адреса.
РЕДАКТИРОВАТЬ Извините за поздний ответ на запрос дополнительной информации (= больше кода).
Я проверил, что указатель 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
-звука в prepareOutputSet
.