NOh*_*Ohs 13 c++ python boost opencl boost-python
编辑:好的,所有的编辑使问题的布局有点混乱,所以我将尝试重写问题(不改变内容,但改进其结构).
如果我将它编译为可执行文件,我有一个openCL程序可以正常工作.现在我尝试使用Python来调用它boost.python.但是,只要我退出Python(导入我的模块后),python就会崩溃.
原因似乎与某些事情有关
程序终止时,仅静态存储GPU CommandQueues及其释放机制
使用的IDE:Visual Studio 2015
使用的操作系统:Windows 7 64位
Python版本:3.5
AMD OpenCL APP 3.0标头
cl2.hpp直接来自Khronos,如下所示:空openCL程序抛出弃用警告
此外,我有一个带有集成图形硬件的Intel CPU,没有其他专用显卡
我使用版本1.60的boost库编译为64位版本
我使用的boost dll称为: boost_python-vc140-mt-1_60.dll
没有python的openCL程序运行正常
没有openCL的python模块工作正常
#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();
}
Run Code Online (Sandbox Code Playgroud)
所以编译程序后dll我启动python并运行以下程序
import FrameWork
exit()
Run Code Online (Sandbox Code Playgroud)
虽然导入工作没有问题,python崩溃了exit().所以我点击调试,Visual Studio告诉我在下面的代码部分(in 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); }
};
Run Code Online (Sandbox Code Playgroud)
如果您将上面的代码编译为一个简单的可执行文件,它可以正常工作.如果满足以下条件之一,代码也可以工作:
CL_DEVICE_TYPE_GPU 被替换为 CL_DEVICE_TYPE_ALL
该行queues.push_back(queue)被删除
那么可能是什么原因以及可能的解决方案是什么?我怀疑它与我的testclass是静态的事实有关,但由于它与可执行文件一起工作,我不知道是什么导致它.
我过去遇到过类似的问题。
clRetain*功能由 提供支持OpenCL1.2。在您的情况下,当获取第一个 GPU 平台 ( platforms[0].getDevices(...)for CL_DEVICE_TYPE_GPU) 的设备时,它必须恰好是一个平台预OpenCL1.2,因此您会崩溃。当获得任何类型的设备(GPU/CPU/...)时,您的第一个平台将更改为 OpenCL1.2+,一切都很好。
要修复问题集:
#define CL_HPP_MINIMUM_OPENCL_VERSION 110
这将确保clRetain*不会对不受支持的平台进行调用(OpenCL 1.2 之前的版本)
更新:我认为存在一个错误,尽管将最低 OpenCL 版本设置为 1.1,但它仍然尝试在 pre 上cl2.hpp使用clRetain*OpenCL1.2尽管将最低 OpenCL 版本设置为 1.1,但在创建命令队列时将最低 OpenCL 版本设置为 110 和版本过滤对我来说效果很好。
完整的工作示例:
#include "stdafx.h"
#include <vector>
#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_TARGET_OPENCL_VERSION 200
#define CL_HPP_MINIMUM_OPENCL_VERSION 110
#include <CL/cl2.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);
size_t x = 0;
for (; x < platforms.size(); ++x)
{
cl::Platform &p = platforms[x];
int v = cl::detail::getPlatformVersion(p());
short version_major = v >> 16;
if (version_major >= 2) // OpenCL 2.x
break;
}
if (x == platforms.size())
return; // no OpenCL 2.0 platform available
platforms[x].getDevices(CL_DEVICE_TYPE_GPU, &devices);
cl::Context context(devices);
cl::CommandQueue queue(context, devices[0]);
queues.push_back(queue);
}
int main()
{
TestClass::getInstance();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
更新2:
那么造成这种情况的原因是什么以及可能的解决方案是什么?我怀疑这与我的测试类是静态的这一事实有关,但由于它与可执行文件一起工作,我不知道是什么导致了它。
TestClass static 似乎是一个原因。从 python 运行时,释放内存的顺序似乎错误。要解决这个问题,您可能需要添加一个方法,必须在 python 开始释放内存之前显式调用该方法来释放 opencl 对象。
static TestClass& getInstance() // <- const removed
{
static TestClass instance;
return instance;
}
void release()
{
queues.clear();
}
BOOST_PYTHON_MODULE(FrameWork)
{
TestClass::getInstance();
TestClass::getInstance().release();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
323 次 |
| 最近记录: |