0

在尝试使用 boost::compute 时,我遇到了确定我可以在设备上分配的最大向量的问题(我对 boost::compute 还是很陌生)。以下代码片段

std::vector<cl_double> host_tmp;
std::cout << "CL_DEVICE_GLOBAL_MEM_SIZE / sizeof(cl_double) = " << device.get_info<cl_ulong>(CL_DEVICE_GLOBAL_MEM_SIZE) / sizeof(cl_double) << "\n";
std::cout << "CL_DEVICE_MAX_MEM_ALLOC_SIZE / sizeof(cl_double) = " << device.get_info<cl_ulong>(CL_DEVICE_MAX_MEM_ALLOC_SIZE) / sizeof(cl_double) << "\n";
size_t num_elements = device.get_info<cl_ulong>(CL_DEVICE_MAX_MEM_ALLOC_SIZE) / sizeof(cl_double);
compute::vector<cl_double> dev_tmp(context);
std::cout << "Maximum size of vector reported by .max_size() = " << dev_tmp.max_size() << "\n";
for (auto i = 0; i < 64; ++i) {
    std::cout << "Resizing device vector to " << num_elements << "...";
    dev_tmp.resize(num_elements, queue);
    std::cout << " done.";
    std::cout << " Assigning host data...";
    host_tmp.resize(num_elements);
    std::iota(host_tmp.begin(), host_tmp.end(), 0);
    std::cout << " done.";
    std::cout << " Copying data from host to device...";
    compute::copy(host_tmp.begin(), host_tmp.end(), dev_tmp.begin(), queue);
    std::cout << " done.\n";
    num_elements += 1024 * 1024;
}

CL_DEVICE_GLOBAL_MEM_SIZE / sizeof(cl_double) = 268435456
CL_DEVICE_MAX_MEM_ALLOC_SIZE / sizeof(cl_double) = 67108864
Maximum size of vector reported by .max_size() = 67108864
Resizing device vector to 67108864... done. Assigning host data... done. Copying data from host to device... done.
Resizing device vector to 68157440... done. Assigning host data... done. Copying data from host to device... done.
...
Resizing device vector to 101711872...Memory Object Allocation Failure

很明显,报告的 max_size() 既不是硬限制也不是强制执行的。我假设为了安全起见,我应该坚持报告的 max_size(),但是,如果我在大小为 max_size() 的设备上分配多个向量,那么我也会收到该Memory Object Allocation Failure消息。

  1. 使用 boost::compute 时处理(和避免)内存分配失败的正确/常用方法是什么?
  2. 如何确定在任何给定时刻可以分配的向量的最大大小(即设备可能已经包含分配的数据)?
  3. 如果我有太多数据,我可以让 boost::compute 自动分块处理它还是我必须自己分解它?
  4. 完成后如何释放设备上的内存?
4

1 回答 1

1
  1. 使用 boost::compute 时处理(和避免)内存分配失败的正确/常用方法是什么?

您只需要遵循与 OpenCL 相同的规则。Boost.Compute 没有添加任何新的限制。您必须记住,在许多 OpenCL 平台上,缓冲区的内存分配是以惰性方式完成的,因此即使创建大小大于CL_DEVICE_MAX_MEM_ALLOC_SIZE成功的缓冲区,它也可能在以后失败(实现定义的行为)。

  1. 如何确定在任何给定时刻可以分配的向量的最大大小(即设备可能已经包含分配的数据)?

我认为这不可能。您始终可以创建分配器类(并将其与 一起使用boost::compute::vector),它将全局跟踪每个设备(使用CL_DEVICE_GLOBAL_MEM_SIZE)并在内存不足时执行您希望它执行的任何操作。但是,您必须记住,OpenCL 内存绑定到上下文而不是设备。

  1. 如果我有太多数据,我可以让 boost::compute 自动分块处理它还是我必须自己分解它?

不,您必须实施一些可以解决此问题的方法。根据您的 OpenCL 平台和支持的 OpenCL 版本,它可以通过多种方式完成。

  1. 完成后如何释放设备上的内存?

boost::compute::vector的析构函数释放设备内存。每个 OpenCL 内存对象(如缓冲区)都有其引用计数器,该计数器由 Boost.Compute 的类适当地增加和减少。注意:迭代器不拥有缓冲区,因此在底层缓冲区被释放后(例如,在boost::compute::vector分配的缓冲区被销毁之后),迭代器停止工作。

于 2017-06-14T22:38:51.780 回答