#visual-c #cuda #nested #device #struct
#visual-c #cuda #вложенный #устройство #структура
Вопрос:
Я пытаюсь скопировать некоторые вложенные структуры в память устройства для использования ядром в симуляторе нейронной сети с ускорением CUDA. Этот код связывается и выполняется, но он выдает некоторые исключения и ошибки CUDA:
typedef struct rdLayer
{
long NeuronQty ;
long DendriteQty ;
cuDoubleComplex *gpuWeights ;
cuDoubleComplex *gpuZOutputs ;
cuDoubleComplex *gpuDeltas ;
cuDoubleComplex *gpuUnWeights ;
} rdLayer;
typedef struct rdNetwork
{
long SectorQty;
double K_DIV_TWO_PI;
double two_pi_div_sect_qty;
cuDoubleComplex *gpuSectorBdry;
long LayerQty;
rdLayer *rLayer;
} rdNetwork;
struct rdLearningSet
{
long EvalMode ;
long SampleQty ;
long InputQty ;
long OutputQty ;
long ContOutputs ;
long SampleIdxReq ;
cuDoubleComplex *gpuXInputs ;
cuDoubleComplex *gpuDOutputs ;
cuDoubleComplex *gpuYOutputs ;
double *gpudSE1024 ;
cuDoubleComplex *gpuOutScalar ;
};
[...]
struct rdLearningSet * rdLearn;
struct rdNetwork * rdNet;
[...]
cudaMalloc(amp;rdNet, sizeof(rdNetwork));
cudaMalloc(amp;rdLearn, sizeof(rdLearningSet));
[...]
cuDoubleComplex * dummy;
struct rdLayer rdlSource, * rdldummy;
[...]
//rdLayer *rLayer;
cudaMalloc(amp;rdldummy, sizeof(rdLayer)*rSes.rNet->LayerQty);
cudaMemcpy( amp;rdNet->rLayer, amp;rdldummy, sizeof(rdLayer*), cudaMemcpyHostToDevice);
for (int L=1; L<rSes.rNet->LayerQty; L ){
// construct layer to be copied
rdlSource.NeuronQty=rSes.rNet->rLayer[L].iNeuronQty
rdlSource.DendriteQty=rSes.rNet->rLayer[L].iDendriteQty
cudaMalloc( amp;rdlSource.gpuWeights, sizeof(cuDoubleComplex) * (rSes.rNet->rLayer[L].DendriteQty 1) * (rSes.rNet->rLayer[L].NeuronQty 1) )
mCheckCudaWorked
cudaMalloc( amp;rdlSource.gpuZOutputs, sizeof(cuDoubleComplex) * (rSes.rNet->rLayer[L].DendriteQty 1) * (rSes.rNet->rLayer[L].NeuronQty 1) )
mCheckCudaWorked
cudaMalloc( amp;rdlSource.gpuDeltas, sizeof(cuDoubleComplex) * (rSes.rNet->rLayer[L].iDendriteQty 1) * (rSes.rNet->rLayer[L].iNeuronQty 1) )
mCheckCudaWorked
cudaMalloc( amp;rdlSource.gpuUnWeights, sizeof(cuDoubleComplex) * (rSes.rNet->rLayer[L].iDendriteQty 1) * (rSes.rNet->rLayer[L].iNeuronQty 1) )
mCheckCudaWorked
//copy layer sructure to Device mem
cudaMemcpyToSymbol( "rdNet->rLayer", amp;rdlSource, sizeof(rdLayer), sizeof(rdLayer) * L, cudaMemcpyHostToDevice );/*! 2D neuron cx weight matrix on GPU */
mCheckCudaWorked
}
[...]
cudaMalloc(amp;dummy, sizeof(cuDoubleComplex) * (rSes.rLearn->SampleQty) * (rSes.rLearn->InputQty 1) ); /*! 2D complex input tuples in GPU. */
cudaMemcpy( amp;rdLearn->gpuXInputs, amp;dummy, sizeof(cuDoubleComplex*), cudaMemcpyHostToDevice );
cudaMemcpy( amp;dummy, amp;rSes.rLearn->gpuXInputs, sizeof(cuDoubleComplex) * (rSes.rLearn->SampleQty) * (rSes.rLearn->InputQty 1), cudaMemcpyHostToDevice);
mCheckCudaWorked
cudaMalloc(amp;dummy, sizeof(cuDoubleComplex) * (rSes.rLearn->SampleQty) * (rSes.rLearn->OutputQty 1) ); /*! 2D desired complex outputs in GPU. */
cudaMemcpy( amp;rdLearn->gpuDOutputs, amp;dummy, sizeof(cuDoubleComplex*), cudaMemcpyHostToDevice );
cudaMemcpy( amp;dummy, amp;rSes.rLearn->gpuDOutputs, sizeof(cuDoubleComplex) * (rSes.rLearn->SampleQty) * (rSes.rLearn->OutputQty 1), cudaMemcpyHostToDevice);
mCheckCudaWorked
[...]
К сожалению, вызов cudaMemcpyToSymbol возвращает ошибку, которая, по словам макроса mCheckCudaWorked, является «недопустимым символом устройства», в то время как последний (cudaMemcpy( amp;dummy, amp;rSes.rLearn->gpuDOutputs …) и третий по счету (cudaMemcpy( amp;dummy, amp;rSes.rLearn->gpuXInputs …) cudaMemcpyвызовы возвращают «недопустимый аргумент».
Я не знаю, как поступить, чтобы эти элементы были скопированы в память устройства и адресованы из кода ядра. amp;dummy и amp;rdldummy положительно возвращаются как указатели на адреса памяти устройства, где ожидает выделенная память, и я могу записать эти указатели в память устройства, но я не могу заставить большую часть значений элементов копироваться в выделенные места. Помогите?
Ответ №1:
Такие поля, как gpuXInputs
должны указывать на память, которая была выделена cudaMalloc
, чтобы они были действительными указателями на память устройства.
Обычно вам нужна хост-версия ваших структур данных, где ваши распределения используют malloc
etc, а затем зеркало этих структур данных на устройстве, которые были выделены через cudaMalloc
. Любые указатели в этих структурах данных должны указывать на правильный тип памяти — вы не можете «смешивать и сопоставлять».
Комментарии:
1. Это то, что я пытаюсь; Я выделяю достаточно памяти устройства для структуры rdLearningSet и сохраняю указатель на нее в rdLEarn. Затем я выделяю достаточно памяти устройства для хранения такого количества наборов входных координат и сохраняю указатель на него в ячейке памяти устройства rdLrean-> gpuXInputs. Кажется, это работает правильно. Но когда я пытаюсь скопировать этот блок наборов cordinate в место назначения указателя, хранящегося как rdLearn-> gpuXInputs, не получается!
2. rdlSource — это место, где я создаю дублирующуюся структуру для копирования. Я не вижу, где я смешиваю типы указателей в структурах, можете ли вы указать на это?
3. Нелегко отлаживать только из этих фреймов кода — я предлагаю вам использовать подход «разделяй и властвуй», пока у вас не возникнет меньшая проблема
4. Я заметил, что в приведенных примерах в CUDA C PDF используется cudaMalloc ((void**)amp;varname, … но cudaMemcpy(varname, … когда дело доходит до копирования. Удаление оператора адреса в проблемных строках приведенного выше кода позволило мне скопировать массивы значений. Как ни странно, сингулярные значения по-прежнему проверяемо копируются снова и снова с amp; на месте.