CUDA - копировать в массив в массиве объектов - PullRequest
0 голосов
/ 03 августа 2011

У меня есть приложение CUDA, над которым я работаю с массивом объектов;каждый объект имеет указатель на массив std::pair<int, double>.Я пытаюсь cudaMemcpy массив объектов, а затем cudaMemcpy массив пар для каждого из объектов, однако это приносит мне всевозможные страдания.Сбой при попытке копирования во внутренний массив;Я не понимаю, как это перенести ...


#include <cuda.h>

#include <cuda_runtime.h>

#include <iostream>

using namespace std;

class Object
{
public:
    int id;
    float something;
    std::pair<int, float> *somePairs;
};

Object *objects;

void initObjects()
{
    objects = new Object[10];

    for( int idx = 0; idx < 10; idx++ )
    {
        objects[idx].id = idx;
        objects[idx].something = (float) idx;
    objects[idx].somePairs = new std::pair<int, float>[10];

        for ( int jdx = 10; jdx < 10; jdx++ )
        {
           objects[idx].somePairs[jdx] = std::pair<int, float>( jdx, (float) jdx );
        }

    }
}



void cudaMemcpyObjects()
{
     Object *devObjects;

     cudaMalloc( &devObjects, sizeof(Object) * 10 );
     cudaMemcpy( devObjects, objects, sizeof(Object) * 10, cudaMemcpyHostToDevice );

     for ( int idx = 0; idx < 10; idx++ )
     {
         size_t pairSetSize = sizeof(std::pair<int, float>) * 10;

         // CRASH HERE ... v
         cudaMalloc( &(devObjects[idx].somePairs), pairSetSize );
         cudaMemcpy( devObjects[idx].somePairs, objects[idx].somePairs,
                     sizeof( std::pair<int, float> ) * 10, cudaMemcpyHostToDevice );

     }


}


int main()
{
    initObjects();
    cudaMemcpyObjects();
    return 0;
}

1 Ответ

6 голосов
/ 03 августа 2011

Мой опыт работы с CUDA только начинается, но я считаю, что ошибка такова:

cudaMalloc - это функция host , которая хочет записать указатель в хост память.Тем не менее, вы передаете ему указатель в device memory!

Чтобы исправить это, вы должны сначала создать указатели устройства и заполнить их в структуре вашего хост-объекта, и только потом скопироватьвсе это на устройство, а также скопировать отдельные пары на устройство.

Схематично:

struct Bar;

struct Foo
{
  int tag;
  Bar * bp;
};

void setup()
{
  Foo * hFoo = new Foo[10];

  Foo * dFoo;
  cudaMalloc(dFoo, sizeof(Foo) * 10);

  for (size_t i = 0; i != 10; ++i)
  {
    Bar * dBar;
    cudaMalloc(&dbar, sizeof(Bar));

    Bar b;  // automatic temporary -- we never keep a host copy of this
    cudaMemcpy(dBar, &b, sizeof(Bar));

    hFoo[i].bp = dBar;    // this is already a device pointer!
  }

  cudaMemcpy(dFoo, hFoo, sizeof(Foo) * 10);
}

При возврате не забудьте, что Foo::bp device указатели, которые вам все еще нужно копировать обратно один за другим!

Вероятно, было бы проще иметь только один автономный класс, который вы можете перемещать за один раз, но это можетне быть практичным или желательным по соображениям локальности памяти.Вы должны тщательно об этом говорить.Если член - просто пара, почему бы не поместить два элемента в основной класс напрямую?

...