CUDA中的cudaMalloc函数是否会同步主机和设备?

8

我知道cudaMemcpy函数可以同步主机和设备之间的数据传输,但是cudaMalloc和cudaFree是否也有同步作用呢?

我的目标是在多个GPU设备上异步地分配/拷贝内存并执行核函数,以下是我代码的简化版本:

void wrapper_kernel(const int &ngpu, const float * const &data)
{
 cudaSetDevice(ngpu);
 cudaMalloc(...);
 cudaMemcpyAsync(...);
 kernels<<<...>>>(...);
 cudaMemcpyAsync(...);
 some host codes;
}

int main()
{
 const int NGPU=3;
 static float *data[NGPU];
 for (int i=0; i<NGPU; i++) wrapper_kernel(i,data[i]);
 cudaDeviceSynchronize();
 some host codes;
}

然而,GPU 以顺序的方式运行,但是无法找到原因。


4
是的,cudaMalloccudaFree是阻塞的,并且在当前GPU上执行的所有内核之间进行同步。 - Jared Hoberock
@Jared Hoberock 谢谢!那么,是否有cudaMalloc或cudaFree的同步版本,就像cudaMemcpyAsync一样? - Hailiang Zhang
@Jared Hoberock 我在上面的评论中指的是异步版本。 - Hailiang Zhang
不行,但你可以通过在内核中调用“malloc”和“free”来自己创建。 - Jared Hoberock
@Jared Hoberock 我有CUDA4.0,我怀疑在内核中调用malloc和free是否受支持。 - Hailiang Zhang
显示剩余2条评论
2个回答

2

尝试为每个GPU使用cudaStream_t。下面是从CUDA示例中获取的simpleMultiGPU.cu。

 //Solver config                                                          
TGPUplan      plan[MAX_GPU_COUNT];
//GPU reduction results                                                                                   
float     h_SumGPU[MAX_GPU_COUNT];

....memory init....

//Create streams for issuing GPU command asynchronously and allocate memory (GPU and System page-locked)                             for (i = 0; i < GPU_N; i++)
{
    checkCudaErrors(cudaSetDevice(i));
    checkCudaErrors(cudaStreamCreate(&plan[i].stream));
    //Allocate memory                                                                                                                    checkCudaErrors(cudaMalloc((void **)&plan[i].d_Data, plan[i].dataN * sizeof(float)));
    checkCudaErrors(cudaMalloc((void **)&plan[i].d_Sum, ACCUM_N * sizeof(float)));
    checkCudaErrors(cudaMallocHost((void **)&plan[i].h_Sum_from_device, ACCUM_N * sizeof(float)));
    checkCudaErrors(cudaMallocHost((void **)&plan[i].h_Data, plan[i].dataN * sizeof(float)));

    for (j = 0; j < plan[i].dataN; j++)
    {
        plan[i].h_Data[j] = (float)rand() / (float)RAND_MAX;
    }
}

....kernel, memory copyback....

这里有一些使用多GPU的指南,点击此处查看。


1
你看到GPU操作顺序执行的最可能原因是cudaMalloc是异步的,而cudaFree不是(只需将它们排队在CPU线程上,并在一系列操作结束时发送释放请求)。
你需要使用固定内存进行从CPU内存到GPU内存的异步传输,Cuda提供了两个实用程序函数cudaMallocHostcudaFreeHost(而不是mallocfree)。另外,还有cudaHostAlloc可以进行更精细的控制,请阅读CUDA手册以获取详细信息。

cudaMalloc是异步的,但更重要的是,除非您为主机上的复制缓冲区分配了一些固定(或页面锁定)内存(如上面@ardiyu07的示例所示),否则异步流复制仍将是顺序的。最有可能的罪魁祸首不是cudaMalloc,而是未固定的主机内存。这可能是他的GPU操作以顺序运行的真正原因。 cudaFree()是同步的。要使其异步,可以在自己的队列中排队释放并从主线程发送cudaFree请求,但通常在所有操作之后释放内存。@talonmies - kisa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接