【问题标题】:will cudaMalloc synchronize host and device?cudaMalloc 会同步主机和设备吗?
【发布时间】:2012-12-08 14:39:40
【问题描述】:

我知道 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 是按顺序运行的,找不到原因。

【问题讨论】:

  • 是的,cudaMalloccudaFree 在当前 GPU 上执行的所有内核之间阻塞和同步。
  • @Jared Hoberock 谢谢!那么,是否有 cudaMalloc 或 cudaFree 的同步版本,例如 cudaMemcpyAsyn?
  • @Jared Hoberock 我的意思是上述评论中的异步版本。
  • 不,但您可以通过在内核内部调用 mallocfree 来制作自己的。
  • @Jared Hoberock 我有 CUDA4.0,但我怀疑是否支持从内核内部调用 malloc 和 free

标签: cuda


【解决方案1】:

尝试对每个 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....

here's 一些使用多GPU的指南。

【讨论】:

    【解决方案2】:

    您看到 GPU 操作按顺序运行的最可能原因是 cudaMalloc 是异步的,但 cudaFree 不是(只需在 CPU 线程上排队并在一系列操作结束时发送空闲请求) .

    您需要使用固定内存进行从 CPU 内存到 GPU 内存的异步传输,Cuda 提供了两个实用函数 cudaMallocHostcudaFreeHost(而不是 mallocfree)。 BTW,还有cudaHostAlloc可以更好的控制,详细阅读CUDA手册。

    【讨论】:

    • cudaMalloc 是异步的,但更重要的是,除非您为主机上的复制缓冲区分配一些固定(或页面锁定)内存(如上面@ardiyu07 的示例所示),否则异步流副本仍将是顺序的。这里最有可能的罪魁祸首不是cudaMalloc,而是未固定的主机内存。这可能是他的 GPU 操作按顺序运行的真正原因。 cudaFree() 是同步的。为了使其异步,您可以自己排队释放并从主线程发送 cudaFree 请求,但您通常在所有操作之后释放内存。 @talonmies
    猜你喜欢
    • 1970-01-01
    • 2012-11-22
    • 1970-01-01
    • 2012-10-14
    • 2012-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多