从每个主机线程启动CUDA流

时间:2011-07-19 17:34:58

标签: cuda

我的目的是使用n个主机线程在NVidia Tesla C2050上同时创建n个流。内核是一个简单的向量乘法...我在n个流之间平均分配数据,每个流都将进行并发执行/数据传输。

数据是浮点数,我有时会得到相同的CPU / GPU总和,有时它们相距很远...我想这可能是因为我的代码丢失了同步结构,对我而言,还有我不认为流之间的任何同步构造是必要的,因为我希望每个CPU都有一个唯一的流来控制,我不关心线程内的异步数据复制和内核执行。

以下是每个线程运行的代码:

//every thread would run this method in conjunction

static CUT_THREADPROC solverThread(TGPUplan *plan)
{

    //Allocate memory
    cutilSafeCall( cudaMalloc((void**)&plan->d_Data, plan->dataN * sizeof(float)) );

    //Copy input data from CPU
    cutilSafeCall( cudaMemcpyAsync((void *)plan->d_Data, (void *)plan->h_Data, plan->dataN * sizeof(float), cudaMemcpyHostToDevice, plan->stream) );
    //to make cudaMemcpyAsync blocking
    cudaStreamSynchronize( plan->stream );

    //launch
    launch_simpleKernel( plan->d_Data, BLOCK_N, THREAD_N, plan->stream);
    cutilCheckMsg("simpleKernel() execution failed.\n");

    cudaStreamSynchronize(plan->stream);

    //Read back GPU results
    cutilSafeCall( cudaMemcpyAsync(plan->h_Data, plan->d_Data, plan->dataN * sizeof(float), cudaMemcpyDeviceToHost, plan->stream) );
    //to make the cudaMemcpyAsync blocking...               
    cudaStreamSynchronize(plan->stream);

    cutilSafeCall( cudaFree(plan->d_Data) );

    CUT_THREADEND;
}

创建多个线程并调用上面的函数:

    for(i = 0; i < nkernels; i++)
            threadID[i] = cutStartThread((CUT_THREADROUTINE)solverThread, &plan[i]);

    printf("main(): waiting for GPU results...\n");
    cutWaitForThreads(threadID, nkernels);

我从其中一个CUDA Code SDK示例中采用了此策略。正如我之前所说的,这段代码有时会起作用,而其他时候它会提供任意的结果。我需要帮助修复此代码...

2 个答案:

答案 0 :(得分:2)

首先,根据我的经验,我不是任何想象力的专家。

我不明白为什么这需要多个主机线程。看起来你正在管理一个设备并传递多个流。我看到这样做的方式(伪代码)

{
create a handle

allocate an array of streams equal to the number of streams you want

for(int n=0;n<NUM_STREAMS;n++)
{
   cudaStreamCreate(&streamArray[n]);
}

}

从那里你可以将数组中的流传递给各种异步调用(cudaMemcpyAsync(),内核流等),然后设备管理其余的。我有多个流的奇怪的可扩展性问题(不要尝试制作10k流,我在GTX460上遇到4-8左右的问题),所以如果遇到这些问题,不要感到惊讶。祝你好运,

约翰

答案 1 :(得分:1)

我打赌是

  

BLOCK_N,THREAD_N

,请勿覆盖您传递的阵列的确切大小。 请提供初始化流的代码和这些缓冲区的大小。

作为旁注,Streams对于重叠计算与内存传输非常有用。在每次异步调用之后同步流是没有用的。