Как я могу скопировать элементы вложенных структур в пространство памяти устройства CUDA?

#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; на месте.