在 boost::compute 中分配大向量

Allocating large vectors in boost::compute

本文关键字:向量 分配 compute boost      更新时间:2023-10-16

在尝试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. 完成后如何释放设备上的内存?
  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之后),迭代器将停止工作。