Возможно, это не самая узкая проблема, но ..
Программа реализует обертку вокруг всего, что связано с OpenCL. Оболочка обнаруживает все устройства OpenCL, а затем оборачивает их в еще одну обертку. Оболочки устройства содержат все связанные с ним объекты, такие как выделенный буфер cl_mem, связанный контекст и т. Д.
Я несколько раз проверял, если нет ошибок, если указатели не используются повторно, как если бы из-за какой-либо ошибки оболочки устройств с разных платформ имели бы один и тот же указатель платформы. но нет.
Проблема:
Когда я делю работу между всеми вычислительными устройствами на моем ноутбуке (CPU + Intel GPU + Nvidia GPU), выполнение ядра, выдаваемое графическому процессору NVIDIA, с CL_INVALID_COMMAND_QUEUE.
Я все проверил.
Я пробовал следующие сценарии:
- Intel GPU и CPU одновременно => все отлично работает
- два процессора одновременно (сервер) => все отлично работает
- , если я смешиваю устройства с двух платформ на ноутбуке => он вылетает с CL_INVALID_COMMAND_QUEUE. сбой ТОЛЬКО на графическом процессоре Nvidia.
большая часть кода инициализации приведена ниже.
std::cout << "Initializing the OpenCL engine..\n";
cl_int ret;
unsigned int nrOfActiveContexts = 0;
ret = clGetPlatformIDs(0, NULL, &mRetNumPlatforms);
if (mRetNumPlatforms > 0)
{
this->mPlatforms.resize(mRetNumPlatforms);
}
else
{
fprintf(stderr, "No OpenCL platform available.\n");
exit(1);
}
ret = clGetPlatformIDs(mRetNumPlatforms, mPlatforms.data(), NULL);
std::vector<cl_device_id> devices;
cl_context context;
cl_uint numberOfDevices;
//query for available compute platforms
for (int i = 0; i < mPlatforms.size() ; i++)
{
bool error = false;
numberOfDevices = 0;
devices.clear();
context = NULL;
cl_device_type deviceTypes = CL_DEVICE_TYPE_ALL;
if (useCPU &&useGPU)
deviceTypes = CL_DEVICE_TYPE_ALL;
else if (useCPU)
deviceTypes = CL_DEVICE_TYPE_CPU;
else if (useGPU)
deviceTypes = CL_DEVICE_TYPE_GPU;
ret = clGetDeviceIDs(mPlatforms[i], deviceTypes, 0, NULL, &numberOfDevices);
if (numberOfDevices > 0)
{
devices.resize( numberOfDevices);
ret = clGetDeviceIDs(mPlatforms[i], deviceTypes,
numberOfDevices, devices.data(), NULL);
}
else continue;
context = clCreateContext(NULL, numberOfDevices, devices.data(), NULL, NULL, &ret);
if (ret != CL_SUCCESS)
throw(std::abort);
mContexts.push_back(context);
if (ret != CL_SUCCESS)
{
error = true;
}
//query device properties create Workers
size_t ret_size;
cl_uint compute_units;
cl_ulong max_alloc;
size_t max_work_size;
std::string name;
std::vector<char> c_name;
for (int y = 0; y < devices.size(); y++)
{
ret_size = compute_units = max_alloc = max_work_size = 0;
c_name.clear();
ret = clGetDeviceInfo(devices[y], CL_DEVICE_NAME, NULL, NULL, &ret_size);
if (ret != CL_SUCCESS)
{
error = true; goto errored;
}
c_name.resize(ret_size);
ret = clGetDeviceInfo(devices[y], CL_DEVICE_NAME, c_name.size(), c_name.data(), &ret_size);
if (ret != CL_SUCCESS)
{
error = true; goto errored;
}
name = std::string(c_name.begin(), c_name.end());
name = std::regex_replace(name, std::regex("[' ']{2,}"), " ");
cl_device_type devType;
ret = clGetDeviceInfo(devices[y], CL_DEVICE_TYPE, sizeof(cl_device_type), (void *)&devType, NULL);
if (ret != CL_SUCCESS)
{
error = true; goto errored;
}
ret = clGetDeviceInfo(devices[y], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), (void *)&compute_units, NULL);
if (ret != CL_SUCCESS)
{
error = true; goto errored;
}
ret = clGetDeviceInfo(devices[y], CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), (void *)&max_work_size, NULL);
if (ret != CL_SUCCESS)
{
error = true; goto errored;
}
CWorker::eWorkerType type;
if (devType & CL_DEVICE_TYPE_GPU)
type = CWorker::eWorkerType::GPU;
else
if (devType & CL_DEVICE_TYPE_CPU)
type = CWorker::eWorkerType::CPU;
if (type == CWorker::eWorkerType::CPU)
{
if (compute_units > 8)
max_work_size = compute_units / 4;
else if (compute_units == 8)
max_work_size = 2;
else
max_work_size = 1;
}
ret = clGetDeviceInfo(devices[y], CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), (void *)&max_alloc, NULL);
if (ret != CL_SUCCESS)
{
error = true;
goto errored;
}
errored:
if (error != true)
{
CWorker * w = new CWorker();
w->setDevice(devices[y]);
w->setMaxComputeUnits(compute_units);
w->setMaxMemAlloc(max_alloc);
w->setMaxWorkGroupSize(max_work_size);
w->setName(name);
std::cmatch cm;
if (std::regex_search(name.data(), cm, std::regex("\\w\+")))
w->setShortName(std::string(cm[0]) +"-"+ std::to_string(mWorkers.size()+1));
w->setContext(context);
w->setType(type);
mWorkers.push_back(w);
}
}
nrOfActiveContexts++;
}
if (mWorkers.size() > 0)
mInitialised = true;
if (mWorkers.size() > 0)
return true;
else return false;