Копирование дерева с несколькими ветвями в память GPU - PullRequest
1 голос
/ 14 июня 2011

У меня есть дерево узлов, и я пытаюсь скопировать его в память GPU.Узел выглядит так:

struct Node
{
   char *Key;
   int ChildCount;
   Node *Children;
}

А моя функция копирования выглядит так:

void CopyTreeToDevice(Node* node_s, Node* node_d)
{


     //allocate node on device and copy host node
     cudaMalloc( (void**)&node_d, sizeof(Node));
     cudaMemcpy(node_d, node_s, sizeof(Node), cudaMemcpyHostToDevice);

     //test
     printf("ChildCount of node_s looks to be : %d\n", node_s->ChildCount);
     printf("Key of node_s looks to be : %s\n", node_s->Key);

     Node *temp;
     temp =(Node *) malloc(sizeof(Node));
     cudaMemcpy(temp, node_d, sizeof(Node), cudaMemcpyDeviceToHost);
     printf("ChildCount of node_d on device is actually : %d\n", temp->ChildCount);
     printf("Key of node_d on device is actually : %s\n", temp->Key);
     free(temp);



     //       continue with child nodes
     if(node_s->ChildCount > 0)
     {
         //problem here
         cudaMalloc( (void**)&(node_d->Children), sizeof(Node)*(node_s->ChildCount));

         cudaMemcpy(node_d->Children, node_s->Children, 
                    sizeof(Node)*node_s->ChildCount, cudaMemcpyHostToDevice);

         for(int i=0;i<node_s->ChildCount;i++)
         {
                 CopyTreeToDevice(&(node_s->Children[i]), &(node_d->Children[i]));
         }
     }

}

Но у меня проблема со строкой:

cudaMalloc( (void**)&(node_d->Children), sizeof(Node)*(node_s->ChildCount));

Дает мне исключение нарушения прав доступа. Тестовый раздел работает гладко. Нет проблем при инициализации полей.

Вот результат теста тестового раздела:

ChildCount of node_s looks to be : 35
Key of node_s looks to be : root
ChildCount of node_d on device is actually : 35
Key of node_d on device is actually : root

В чем причина этого?

Спасибо.

Ответы [ 2 ]

4 голосов
/ 14 июня 2011

node_d->Children - это переменная, которая находится в коде устройства.Вы не можете использовать его непосредственно вашим кодом хоста, как вы делаете со вторым cudaMalloc.Более того, копирование указателей хоста на устройство не имеет особого смысла, поскольку вы не можете разыменовать их в коде устройства.

Более приятный и быстрый способ заключается в следующем:

  • Предварительно выделить большоймассив для всего дерева.
  • Используйте индекс массива вместо указателей.Действительность индексов будет сохраняться при передаче на устройство и с него.
  • Выделите весь массив один раз на устройстве.Наличие нескольких memAlloc может быть неэффективным (особенно в системах Windows, когда монитор подключен к этому графическому процессору).Кроме того, поскольку memAlloc возвращает адрес, который всегда выровнен по 512 байтам, вы практически не можете выделить меньшие порции памяти.Итак, согласно вашему текущему коду, каждый дочерний массив будет занимать не менее 512 байт, даже если внутри него только 2 дочерних элемента.
  • Скопируйте весь массив один раз с хоста на устройство.Это намного быстрее, чем использование нескольких команд memCopy, даже если вы на самом деле копируете некоторую дополнительную область памяти, которая не используется.
2 голосов
/ 14 июня 2011

Похоже, сам node_d находится на графическом процессоре. Вы не можете получить доступ к структурам на GPU, используя -> или. Вам необходимо скопировать обратно node_d на хост, выделить необходимые данные и скопировать их обратно.

...