Выделение больших векторов в 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?
  2. Как определить наибольший размер вектора, который я могу выделить в любой момент (т. Е. Устройство может уже содержать выделенные данные)?
  3. Если у меня слишком много данных, могу ли я получить boost :: compute для автоматической обработки в блоках или мне придется разбить их самостоятельно?
  4. Как освободить память на устройстве, когда я закончу с ним?

0

Решение

  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 который выделил этот буфер уничтожен), итераторы перестают работать.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]