EDIT: Хорошо, все изменения сделали макет вопроса немного запутанным, поэтому я попытаюсь переписать вопрос (не меняя контент, а улучшая его структуру).
Короче говоря
У меня есть openCL-программа, которая отлично работает, если я скомпилирую ее как исполняемый файл. Теперь я пытаюсь сделать его вызываемым из Python с помощью boost.python
. Однако, как только я выхожу из Python (после импорта моего модуля), сбой python.
Причина, похоже, связана с
статически сохраняя только GPU CommandQueues и механизм их выпуска, когда программа завершает
MWE и настройка
Настройка
-
Используемая среда IDE: Visual Studio 2015
-
Используемая ОС: Windows 7 64bit
-
Версия Python: 3.5
-
Заголовки AMD OpenCL APP 3.0
-
cl2.hpp
прямо из Khronos, как предлагается здесь: пустая программа openCL выдает предупреждение об отказе -
Также у меня есть процессор Intel со встроенным графическим оборудованием и никакой другой выделенной графической картой.
-
Я использую версию 1.60 библиотеки boost, скомпилированную как 64-разрядные версии
-
Я использую dll boost:
boost_python-vc140-mt-1_60.dll
-
Программа openCL без python отлично работает
-
Модуль python без openCL отлично работает
MWE
#include <vector>
#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_TARGET_OPENCL_VERSION 200
#define CL_HPP_MINIMUM_OPENCL_VERSION 200 // I have the same issue for 100 and 110
#include "cl2.hpp"
#include <boost/python.hpp>
using namespace std;
class TestClass
{
private:
std::vector<cl::CommandQueue> queues;
TestClass();
public:
static const TestClass& getInstance()
{
static TestClass instance;
return instance;
}
};
TestClass::TestClass()
{
std::vector<cl::Device> devices;
vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
//remove non 2.0 platforms (as suggested by doqtor)
platforms.erase(
std::remove_if(platforms.begin(), platforms.end(),
[](const cl::Platform& platform)
{
int v = cl::detail::getPlatformVersion(platform());
short version_major = v >> 16;
return !(version_major >= 2);
}),
platforms.end());
//Get all available GPUs
for (const cl::Platform& pl : platforms)
{
vector<cl::Device> plDevices;
try {
pl.getDevices(CL_DEVICE_TYPE_GPU, &plDevices);
}
catch (cl::Error&)
{
// Doesn't matter. No GPU is available on the current machine for
// this platform. Just check afterwards, that you have at least one
// device
continue;
}
devices.insert(end(devices), begin(plDevices), end(plDevices));
}
cl::Context context(devices[0]);
cl::CommandQueue queue(context, devices[0]);
queues.push_back(queue);
}
int main()
{
TestClass::getInstance();
return 0;
}
BOOST_PYTHON_MODULE(FrameWork)
{
TestClass::getInstance();
}
Вызов программы
Итак, после компиляции программы как dll
я запускаю python и запускаю следующую программу
import FrameWork
exit()
В то время как импорт работает без проблем, python падает с exit()
. Поэтому я нажимаю на debug, и Visual Studio сообщает мне, что в следующем разделе кода (в cl2.hpp
) есть исключение:
template <>
struct ReferenceHandler<cl_command_queue>
{
static cl_int retain(cl_command_queue queue)
{ return ::clRetainCommandQueue(queue); }
static cl_int release(cl_command_queue queue) // -- HERE --
{ return ::clReleaseCommandQueue(queue); }
};
Если вы скомпилируете вышеуказанный код вместо простого исполняемого файла, он работает без проблем. Также код работает, если выполняется одно из следующих условий:
-
CL_DEVICE_TYPE_GPU
заменяется наCL_DEVICE_TYPE_ALL
-
удаляется строка
queues.push_back(queue)
Вопрос
Итак, какова может быть причина этого и какие возможные решения? Я подозреваю, что это связано с тем, что мой тестовый класс является статическим, но поскольку он работает с исполняемым файлом, я не понимаю, что его вызывает.