我的目的是使用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示例中采用了此策略。正如我之前所说的,这段代码有时会起作用,而其他时候它会提供任意的结果。我需要帮助修复此代码...
答案 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对于重叠计算与内存传输非常有用。在每次异步调用之后同步流是没有用的。