2013-02-23 2 views
0

Я хочу, чтобы сгенерировать дерево решений на CUDA, ниже мы имеем псевдо-код (код очень примитивно, это только понять, что я написал):Genarating дерева решений на CUDA

class Node 
{ 
public : 
    Node* father; 
    Node** sons; 
    int countSons; 

    __device__ __host__ Node(Node* father) 
    { 
     this->father = father; 
     sons = NULL; 
    } 
}; 

__global__ void GenerateSons(Node** fathers, int countFathers*, Node** sons, int* countSons) 
{ 
    int Thread_Index = (blockDim.x * blockIdx.x) + threadIdx.x; 

    if(Thread_Index < *(countFathers)) 
    { 
     Node* Thread_Father = fathers[Thread_Index]; 
     Node** Thread_Sons; 
     int Thread_countSons; 
     //Now we are creating new sons for our Thread_Father 
     /* 
     * Generating Thread_Sons for Thread_Father; 
     */ 
     Thread_Father->sons = Thread_Sons; 
     Thread_Father->countSons = Thread_countSons; 

     //Wait for others 
      /*I added here __syncthreads because I want to count all generated sons 
      by threads 
      */ 
      *(countSons) += Thread_countSons; 
     __syncthreads(); 

     //Get all generated sons from whole Block and copy to sons 

     if(threadIdx.x == 0) 
     { 
      sons = new Node*[*(countSons)]; 
     } 
     /*I added here __syncthreads because I want to allocated array for sons 
      */ 
     __syncthreads(); 

     int Thread_Offset; 
     /* 
     * Get correct offset for actual thread 
     */ 
     for(int i = 0; i < Thread_countSons; i++) 
      sons[Thread_Offset + i] = Thread_Sons[i]; 
    } 
} 

void main() 
{ 
    Node* root = new Node(); 
    //transfer root to kernel by cudaMalloc and cudaMemcpy 
    Node* root_d = root->transfer(); 

    Node** fathers_d; 
    /* 
    * preapre array with father root and copy him to kernel 
    */ 

    int* countFathers, countSons; 
    /* 
    * preapre pointer of int for kernel and for countFathers set value 1 
    */ 

    for(int i = 0; i < LevelTree; i++) 
    { 
     Node** sons = NULL; 
     int threadsPerBlock = 256; 
     int blocksPerGrid = (*(countFathers)/*get count of fathers*/ + threadsPerBlock - 1)/threadsPerBlock; 
     GenerateSons<<<blocksPerGrid , threadsPerBlock >>>(fathers_d, countFathers, sons, countSons); 
     //Wait for end of kernel call 
     cudaDeviceSynchronize(); 

     //replace 
     fathers_d = sons; 
     countFathers = countSons; 
    } 
} 

Итак, это работает для 5-уровневого (генерируя дерево решений для шашек), но на 6-уровне я имею ошибку. В некотором месте в коде ядра malloc возвращает NULL, и для меня это информация о том, что некоторые потоки в blockThreads не могут выделить больше памяти. Я уверен, что я очищаю весь объект, который мне не нужен, на каждом конце ядра вызова. Я думаю, что я не могу понять некоторые факты использования памяти в CUDA. Если я создаю объект в локальной памяти потока, а ядро ​​заканчивает его действие, то в начале ядра я вижу, что узлы от первого вызова ядра. Итак, мой вопрос в том, где хранятся объекты Node от первого вызова ядра? Сохраняются ли они в локальной памяти потока в блоке? Итак, если это правда, то при каждом вызове моей функции ядра я уменьшу пространство локальной памяти этого потока?

Извините за мой плохой английский, если что-то неясно.

Я использую GT 555M с Compute возможностями 2.1, CUDA SDK 5.0, Visual Studio 2010 Premium с Nsight 3,0

+0

Вы вызываете новое в ядре и никогда не вызываете delete. Поскольку вы используете ____global____ void GenerateSons, я готов поспорить, что на устройстве у вас заканчивается память. – AlexLordThorsen

+0

Хорошо, мое устройство имеет 2 ГБ пространства и sizeof (Node) = 28. Первый вызов genrate 7 сыновей, секунд 49, следующий 379 и последний правильный вызов 2769. Итак, мое устройство сгенерировало 3204 сыновей, которые дают 87Kb ??? – waskithebest

+0

hmmm, мне интересно, если новый вытаскивает память из разделяемой памяти. Мне придется искать документацию. – AlexLordThorsen

ответ

2

Окей,

Я обнаружил, что, new и malloc пробуждают в ядре выделяется в глобальная память на устройстве. Также я нашел это

По умолчанию CUDA создает кучу 8 МБ.

CUDA Application Design and Development, page 128

Таким образом, я использовал этот метод cudaDeviceSetLimit(cudaLimitMallocHeapSize, 128*1024*1024); для увеличения динамической памяти на устройстве до 128Mb и программ генерируемых правильно на 6 уровень дерева (22110 сынов), но на самом деле я получаю некоторые утечки памяти. который мне нужно найти.

Смежные вопросы