0

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の使用メモリーの事実がわからないと思います。スレッドのローカルメモリにオブジェクトを作成していて、カーネルがアクティビティを終了した場合、カーネルの2番目の開始時に、カーネルの最初の呼び出しからのノードがであることがわかります。だから私の質問は、オブジェクトがどこにあるかですNode最初のカーネル呼び出しから保存されますか?それらはブロック内のスレッドのローカルメモリに保存されていますか?それで、それが本当なら、カーネル関数を呼び出すたびに、このスレッドのローカルメモリのスペースを減らしますか?

コンピューティング機能2.1を備えたGT555m、CUDA SDK 5.0、NSight3.0を備えたVisualStudio2010Premiumを使用しています

4

1 に答える 1

2

オーケー、

カーネルnewでのinvokeは、デバイスのグローバルメモリに割り当てられていることがわかりました。また、私はこれを見つけましたmalloc

デフォルトでは、CUDAは8MBのヒープを作成します。

CUDAアプリケーションの設計と開発、128ページ

そのため、この方法を使用cudaDeviceSetLimit(cudaLimitMallocHeapSize, 128*1024*1024);してデバイスのヒープメモリを128Mbに増やし、プログラムは6レベルのツリー(22110息子)を正しく生成しましたが、実際にはメモリリークが発生します...これを見つける必要があります。

于 2013-02-24T17:38:40.163 に答える