OpenCL多GPU缓冲区读取失败

时间:2014-01-02 01:27:18

标签: c opencl gpgpu multi-gpu

我试图让2个Nvidia GPU并排工作来进行n体模拟(源)。我做了正确的检测,并将所有OpenCL内容存储在一个结构中:

struct ocl_wrap {
  cl_event event;
  cl_program program;
  cl_kernel kernel;
  cl_command_queue command_queue;
  cl_device_id device_id;
  cl_context context;

  cl_mem masses;
  cl_mem bodies;
  cl_mem speeds;
  cl_mem newBodies;

  cl_int ret;
};

所以现在,每个设备都分配了自己的结构(它自己的上下文,队列等),每一步我运行这2个函数:

void writeGPU() {
      clCreateBuffer() //4* 
      clSetKernelArg() //5*
      clEnqueueNDRangeKernel()
}
void readGPU() {
      clEnqueueReadBuffer() //2*
      clFlush()
      clReleaseMemObject() //4*
}

一步看起来像这样:

void step() {
  for each gpu
    writeGPU();
  runCPU();
  for each gpu
    readGPU();
}

每个设备都有一部分需要解决的问题。

我遇到一个问题,即我尝试复制回CPU的第一个64(有时是128)从一个或另一个GPU浮动,实际上不会复制。否则,一切正常,第一个GPU完美无缺。有时它只是起作用,但随机出现的bug就不会消失了。有什么建议吗?

2 个答案:

答案 0 :(得分:0)

我在这一点上的猜测是你可能没有使用 OpenCL事件系统甚至 OpenCL内存屏障/栅栏来获得有关I / O的通知读写已到达目的地,并通过设置断点和等待列表来协调您的程序。如果您系统上的OpenCL分发工具包正常工作并且您正在使用事件系统,那么上面提供的程序序列应该类似于

// setup global event objects
// setup global markers/barriers
void writeGPU() {
      // hook event listeners to APIs
      clCreateBuffer() //4* 
      clSetKernelArg() //5*
      clEnqueueNDRangeKernel()
      // place appropriate markers/barriers
}
void readGPU() {
      // Many OpenCL APIs listen to events and proceed only 
      // when the `wait` condition is satisfied or 
      // barrier conditions are met.
      clEnqueueReadBuffer() //2*
      clFlush()
      clReleaseMemObject() //4*
}

答案 1 :(得分:0)

您可能在阅读完成之前查看数据。 clFlush仅确保命令离开主机,而不是命令在设备上完成。解决方案:使用阻止读取,或使用clFinish代替clFlush,或使用OpenCL事件。