在 boost::compute 中分配大向量

Allocating large vectors in boost::compute

在试验 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 时,correct/usual 处理(和避免)内存分配失败的方法是什么?
  2. 如何确定在任何给定时刻我可以分配的最大矢量大小(即设备可能已经包含分配的数据)?
  3. 如果我有太多数据,我可以 boost::compute 自动分块处理吗?还是我必须自己分解?
  4. 使用完后如何释放设备上的内存?
  1. What is the correct/usual way to deal with (and avoid) memory allocation failures when using boost::compute?

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

  1. How can I determine the largest size of a vector that I can allocate at any given moment (i.e. the device may already contain allocated data)?

我认为这不可能。你总是可以创建你的分配器 class(并将其与 boost::compute::vector 一起使用),它将全局跟踪每个设备(使用 CL_DEVICE_GLOBAL_MEM_SIZE)并在没有足够的时候做任何你想做的事情记忆。但是,您必须记住,OpenCL 内存绑定到上下文而不是设备。

  1. If I have too much data, can I get boost::compute to automatically process it in chunks or do I have to break it up myself?

不,您必须实施一些措施来解决这个问题。它可以通过多种方式完成,具体取决于您的 OpenCL 平台和支持的 OpenCL 版本。

  1. How do I free up memory on the device once I'm done with it?

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