多设备环境下的OpenCL缓冲区实例化

OpenCL Buffer Instantiation in a Multi Device Environment

本文关键字:OpenCL 缓冲区 实例化 环境      更新时间:2023-10-16

我想知道系统端cl::Buffer对象如何在多设备上下文中实例化。

假设我有一个OCL环境类,它从cl::Platform生成一个cl::Context:

this->ocl_context = cl::Context(CL_DEVICE_TYPE_GPU, con_prop);

然后,对应的设备集合:

this->ocl_devices = this->ocl_context.getInfo<CL_CONTEXT_DEVICES>();

我为每个设备生成一个cl::CommandQueue对象和一组cl::Kernel(s)。

假设我有4个相同类型的gpu。现在我有4x cl::Device对象在ocl_devices.

现在,当我有第二个处理程序类来管理每个设备上的计算时会发生什么:

oclHandler h1(cl::Context* c, cl::CommandQueue  cq1, std::vector<cl::Kernel*> k1);
...
oclHandler h2(cl::Context* c, cl::CommandQueue  cq4, std::vector<cl::Kernel*> k4);

然后在每个CLASS中,我都实例化了:

oclHandler::classMemberFunction(
...
  this->buffer =
    cl::Buffer(
      *(this->ocl_context),
      CL_MEM_READ_WRITE,
      mem_size,
      NULL,
      NULL
    );
...
)

之后,写入

oclHandler::classMemberFunction(
...
this->ocl_cq->enqueueWriteBuffer(
      this->buffer,
      CL_FALSE,
      static_cast<unsigned int>(0),
      mem_size,
      ptr,
      NULL,
      NULL
    );
...
this->ocl_cq.finish();
...
)

每个缓冲区。由于实例化是针对cl::上下文的,而不是绑定到特定的设备,因此可能会在每个设备上分配四倍的内存地址。我无法确定何时发生"在设备上,此缓冲区从0xXXXXXXXXXXXXXXXX运行N字节"的操作。

应该为每个设备实例化一个上下文吗?这似乎不自然,因为我必须实例化一个上下文。看看有多少设备,然后实例化d-1更多上下文....似乎是低效的。我关心的是限制可用内存设备方面。我正在对大量数据集进行计算,我可能会使用每张卡上所有可用的6GB内存。

谢谢。

编辑:是否有一种方法来实例化一个缓冲区,并填充它异步不使用命令队列?比如说,我有4个设备,其中一个缓存主机端充满了静态只读数据。假设缓冲区的大小是500MB。如果我想使用clCreateBuffer,带

shared_buffer = new
cl::Buffer(
  this->ocl_context,
  CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR,
  total_mem_size,
  ptr
  NULL
);

将开始阻塞写,在这里我不能做任何主机端,直到所有的ptr的内容被复制到新分配的内存。我有一个多线程设备管理系统,我为每个设备创建了一个cl::CommandQueue,总是为所需的每个内核::setArg传递&shared_buffer。我真不知道该怎么办

当你有一个包含多个设备的上下文时,你在该上下文中创建的任何缓冲区对它的所有设备都是可见的。这意味着上下文中的任何设备都可以从上下文中的任何缓冲区中读取数据,并且OpenCL实现负责确保数据在需要时实际移动到正确的设备。如果多个设备同时尝试访问同一个缓冲区,会发生什么情况,这是一些灰色地带,但这种行为通常是避免的。

虽然所有的缓冲区对所有的设备都是可见的,但这并不一定意味着它们将被分配到所有的设备上。我使用过的所有OpenCL实现都使用"首次使用时分配"策略,即缓冲区仅在该设备需要时才在该设备上分配。所以在你的特殊情况下,你应该为每个设备设置一个缓冲区,只要每个缓冲区只被一个设备使用。

理论上,OpenCL实现可能会预先分配所有设备上的所有缓冲区,以防万一它们需要,但我不希望这种情况在现实中发生(我当然从未见过这种情况发生)。如果您运行在一个有可用GPU分析器的平台上,您可以经常使用分析器来查看缓冲区分配和数据移动实际发生的时间和地点,以使自己确信系统没有做任何不希望发生的事情。