ocl: added OpenCL device selection via OPENCV_OPENCL_DEVICE environment variable
This commit is contained in:
parent
dd9ff587dc
commit
16adbda4d3
@ -51,6 +51,8 @@ const char * impls[] =
|
||||
#endif
|
||||
};
|
||||
|
||||
using namespace cv::ocl;
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
const char * keys =
|
||||
@ -59,42 +61,49 @@ int main(int argc, char ** argv)
|
||||
"{ p | platform | -1 | set platform id }"
|
||||
"{ d | device | 0 | set device id }";
|
||||
|
||||
CommandLineParser cmd(argc, argv, keys);
|
||||
if (cmd.get<bool>("help"))
|
||||
if (getenv("OPENCV_OPENCL_DEVICE") == NULL) // TODO Remove this after buildbot updates
|
||||
{
|
||||
cout << "Available options besides google test option:" << endl;
|
||||
cmd.printParams();
|
||||
return 0;
|
||||
CommandLineParser cmd(argc, argv, keys);
|
||||
if (cmd.get<bool>("help"))
|
||||
{
|
||||
cout << "Available options besides google test option:" << endl;
|
||||
cmd.printParams();
|
||||
return 0;
|
||||
}
|
||||
|
||||
string type = cmd.get<string>("type");
|
||||
int pid = cmd.get<int>("platform");
|
||||
int device = cmd.get<int>("device");
|
||||
|
||||
int flag = type == "cpu" ? cv::ocl::CVCL_DEVICE_TYPE_CPU :
|
||||
cv::ocl::CVCL_DEVICE_TYPE_GPU;
|
||||
|
||||
cv::ocl::PlatformsInfo platformsInfo;
|
||||
cv::ocl::getOpenCLPlatforms(platformsInfo);
|
||||
if (pid >= (int)platformsInfo.size())
|
||||
{
|
||||
std::cout << "platform is invalid\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cv::ocl::DevicesInfo devicesInfo;
|
||||
int devnums = cv::ocl::getOpenCLDevices(devicesInfo, flag, (pid < 0) ? NULL : platformsInfo[pid]);
|
||||
if (device < 0 || device >= devnums)
|
||||
{
|
||||
std::cout << "device/platform invalid\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cv::ocl::setDevice(devicesInfo[device]);
|
||||
}
|
||||
|
||||
string type = cmd.get<string>("type");
|
||||
int pid = cmd.get<int>("platform");
|
||||
int device = cmd.get<int>("device");
|
||||
const DeviceInfo& deviceInfo = cv::ocl::Context::getContext()->getDeviceInfo();
|
||||
|
||||
int flag = type == "cpu" ? cv::ocl::CVCL_DEVICE_TYPE_CPU :
|
||||
cv::ocl::CVCL_DEVICE_TYPE_GPU;
|
||||
|
||||
cv::ocl::PlatformsInfo platformsInfo;
|
||||
cv::ocl::getOpenCLPlatforms(platformsInfo);
|
||||
if (pid >= (int)platformsInfo.size())
|
||||
{
|
||||
std::cout << "platform is invalid\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cv::ocl::DevicesInfo devicesInfo;
|
||||
int devnums = cv::ocl::getOpenCLDevices(devicesInfo, flag, (pid < 0) ? NULL : platformsInfo[pid]);
|
||||
if (device < 0 || device >= devnums)
|
||||
{
|
||||
std::cout << "device/platform invalid\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cv::ocl::setDevice(devicesInfo[device]);
|
||||
|
||||
cout << "Device type:" << type << endl
|
||||
<< "Platform name:" << devicesInfo[device]->platform->platformName << endl
|
||||
<< "Device name:" << devicesInfo[device]->deviceName << endl;
|
||||
cout << "Device type: " << (deviceInfo.deviceType == CVCL_DEVICE_TYPE_CPU ?
|
||||
"CPU" :
|
||||
(deviceInfo.deviceType == CVCL_DEVICE_TYPE_GPU ? "GPU" : "unknown")) << endl
|
||||
<< "Platform name: " << deviceInfo.platform->platformName << endl
|
||||
<< "Device name: " << deviceInfo.deviceName << endl;
|
||||
|
||||
CV_PERF_TEST_MAIN_INTERNALS(ocl, impls)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@
|
||||
#include "cl_programcache.hpp"
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER >= 1200
|
||||
# pragma warning( disable: 4100 4101 4127 4244 4267 4510 4512 4610)
|
||||
#pragma warning( disable: 4100 4101 4127 4244 4267 4510 4512 4610)
|
||||
#endif
|
||||
#undef __CL_ENABLE_EXCEPTIONS
|
||||
#include <CL/cl.hpp>
|
||||
@ -118,8 +118,211 @@ static bool parseOpenCLVersion(const std::string& versionStr, int& major, int& m
|
||||
return true;
|
||||
}
|
||||
|
||||
static void split(const std::string &s, char delim, std::vector<std::string> &elems) {
|
||||
std::stringstream ss(s);
|
||||
std::string item;
|
||||
while (std::getline(ss, item, delim)) {
|
||||
elems.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<std::string> split(const std::string &s, char delim) {
|
||||
std::vector<std::string> elems;
|
||||
split(s, delim, elems);
|
||||
return elems;
|
||||
}
|
||||
|
||||
// Layout: <Platform>:<CPU|GPU|ACCELERATOR|nothing=GPU/CPU>:<deviceName>
|
||||
// Sample: AMD:GPU:
|
||||
// Sample: AMD:GPU:Tahiti
|
||||
// Sample: :GPU|CPU: = '' = ':' = '::'
|
||||
static bool parseOpenCLDeviceConfiguration(const std::string& configurationStr,
|
||||
std::string& platform, std::vector<std::string>& deviceTypes, std::string& deviceNameOrID)
|
||||
{
|
||||
std::string deviceTypesStr;
|
||||
size_t p0 = configurationStr.find(':');
|
||||
if (p0 != std::string::npos)
|
||||
{
|
||||
size_t p1 = configurationStr.find(':', p0 + 1);
|
||||
if (p1 != std::string::npos)
|
||||
{
|
||||
size_t p2 = configurationStr.find(':', p1 + 1);
|
||||
if (p2 != std::string::npos)
|
||||
{
|
||||
std::cerr << "ERROR: Invalid configuration string for OpenCL device" << std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume platform + device types + device name/id
|
||||
platform = configurationStr.substr(0, p0);
|
||||
deviceTypesStr = configurationStr.substr(p0 + 1, p1 - (p0 + 1));
|
||||
deviceNameOrID = configurationStr.substr(p1 + 1, configurationStr.length() - (p1 + 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume platform + device types
|
||||
platform = configurationStr.substr(0, p0);
|
||||
deviceTypesStr = configurationStr.substr(p0 + 1, configurationStr.length() - (p0 + 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume only platform
|
||||
platform = configurationStr;
|
||||
}
|
||||
deviceTypes = split(deviceTypesStr, '|');
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __deviceSelected = false;
|
||||
static bool selectOpenCLDevice()
|
||||
{
|
||||
__deviceSelected = true;
|
||||
|
||||
std::string platform;
|
||||
std::vector<std::string> deviceTypes;
|
||||
std::string deviceName;
|
||||
const char* configuration = getenv("OPENCV_OPENCL_DEVICE");
|
||||
if (configuration)
|
||||
{
|
||||
if (!parseOpenCLDeviceConfiguration(std::string(configuration), platform, deviceTypes, deviceName))
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isID = false;
|
||||
int deviceID = -1;
|
||||
if (deviceName.length() == 1)
|
||||
// We limit ID range to 0..9, because we want to write:
|
||||
// - '2500' to mean i5-2500
|
||||
// - '8350' to mean AMD FX-8350
|
||||
// - '650' to mean GeForce 650
|
||||
// To extend ID range change condition to '> 0'
|
||||
{
|
||||
isID = true;
|
||||
for (size_t i = 0; i < deviceName.length(); i++)
|
||||
{
|
||||
if (!isdigit(deviceName[i]))
|
||||
{
|
||||
isID = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isID)
|
||||
{
|
||||
deviceID = atoi(deviceName.c_str());
|
||||
CV_Assert(deviceID >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
const PlatformInfo* platformInfo = NULL;
|
||||
if (platform.length() > 0)
|
||||
{
|
||||
PlatformsInfo platforms;
|
||||
getOpenCLPlatforms(platforms);
|
||||
for (size_t i = 0; i < platforms.size(); i++)
|
||||
{
|
||||
if (platforms[i]->platformName.find(platform) != std::string::npos)
|
||||
{
|
||||
platformInfo = platforms[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (platformInfo == NULL)
|
||||
{
|
||||
std::cerr << "ERROR: Can't find OpenCL platform by name: " << platform << std::endl;
|
||||
goto not_found;
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceTypes.size() == 0)
|
||||
{
|
||||
if (!isID)
|
||||
{
|
||||
deviceTypes.push_back("GPU");
|
||||
deviceTypes.push_back("CPU");
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceTypes.push_back("ALL");
|
||||
}
|
||||
}
|
||||
for (size_t t = 0; t < deviceTypes.size(); t++)
|
||||
{
|
||||
int deviceType = 0;
|
||||
if (deviceTypes[t] == "GPU")
|
||||
{
|
||||
deviceType = CVCL_DEVICE_TYPE_GPU;
|
||||
}
|
||||
else if (deviceTypes[t] == "CPU")
|
||||
{
|
||||
deviceType = CVCL_DEVICE_TYPE_CPU;
|
||||
}
|
||||
else if (deviceTypes[t] == "ACCELERATOR")
|
||||
{
|
||||
deviceType = CVCL_DEVICE_TYPE_ACCELERATOR;
|
||||
}
|
||||
else if (deviceTypes[t] == "ALL")
|
||||
{
|
||||
deviceType = CVCL_DEVICE_TYPE_ALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "ERROR: Unsupported device type for OpenCL device (GPU, CPU, ACCELERATOR): " << deviceTypes[t] << std::endl;
|
||||
goto not_found;
|
||||
}
|
||||
|
||||
DevicesInfo devices;
|
||||
getOpenCLDevices(devices, deviceType, platformInfo);
|
||||
|
||||
for (size_t i = (isID ? deviceID : 0);
|
||||
(isID ? (i == (size_t)deviceID) : true) && (i < devices.size());
|
||||
i++)
|
||||
{
|
||||
if (isID || devices[i]->deviceName.find(deviceName) != std::string::npos)
|
||||
{
|
||||
// check for OpenCL 1.1
|
||||
if (devices[i]->deviceVersionMajor < 1 ||
|
||||
(devices[i]->deviceVersionMajor == 1 && devices[i]->deviceVersionMinor < 1))
|
||||
{
|
||||
std::cerr << "Skip unsupported version of OpenCL device: " << devices[i]->deviceName
|
||||
<< "(" << devices[i]->platform->platformName << ")" << std::endl;
|
||||
continue; // unsupported version of device, skip it
|
||||
}
|
||||
try
|
||||
{
|
||||
setDevice(devices[i]);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "ERROR: Can't select OpenCL device: " << devices[i]->deviceName
|
||||
<< "(" << devices[i]->platform->platformName << ")" << std::endl;
|
||||
goto not_found;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
not_found:
|
||||
std::cerr << "ERROR: Required OpenCL device not found, check configuration: " << (configuration == NULL ? "" : configuration) << std::endl
|
||||
<< " Platform: " << (platform.length() == 0 ? "any" : platform) << std::endl
|
||||
<< " Device types: ";
|
||||
for (size_t t = 0; t < deviceTypes.size(); t++)
|
||||
{
|
||||
std::cerr << deviceTypes[t] << " ";
|
||||
}
|
||||
std::cerr << std::endl << " Device name: " << (deviceName.length() == 0 ? "any" : deviceName) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
static cv::Mutex __initializedMutex;
|
||||
static bool __initialized = false;
|
||||
static int initializeOpenCLDevices()
|
||||
{
|
||||
assert(!__initialized);
|
||||
__initialized = true;
|
||||
|
||||
assert(global_devices.size() == 0);
|
||||
|
||||
std::vector<cl::Platform> platforms;
|
||||
@ -284,8 +487,6 @@ protected:
|
||||
}
|
||||
~ContextImpl();
|
||||
public:
|
||||
|
||||
static ContextImpl* getContext();
|
||||
static void setContext(const DeviceInfo* deviceInfo);
|
||||
|
||||
bool supportsFeature(FEATURE_TYPE featureType) const;
|
||||
@ -298,6 +499,28 @@ static ContextImpl* currentContext = NULL;
|
||||
|
||||
Context* Context::getContext()
|
||||
{
|
||||
if (currentContext == NULL)
|
||||
{
|
||||
if (!__initialized || !__deviceSelected)
|
||||
{
|
||||
cv::AutoLock lock(__initializedMutex);
|
||||
if (!__initialized)
|
||||
{
|
||||
if (initializeOpenCLDevices() == 0)
|
||||
{
|
||||
CV_Error(CV_GpuNotSupported, "OpenCL not available");
|
||||
}
|
||||
}
|
||||
if (!__deviceSelected)
|
||||
{
|
||||
if (!selectOpenCLDevice())
|
||||
{
|
||||
CV_Error(CV_GpuNotSupported, "Can't select OpenCL device");
|
||||
}
|
||||
}
|
||||
}
|
||||
CV_Assert(currentContext != NULL);
|
||||
}
|
||||
return currentContext;
|
||||
}
|
||||
|
||||
@ -422,13 +645,11 @@ void ContextImpl::setContext(const DeviceInfo* deviceInfo)
|
||||
}
|
||||
}
|
||||
|
||||
ContextImpl* ContextImpl::getContext()
|
||||
{
|
||||
return currentContext;
|
||||
}
|
||||
|
||||
int getOpenCLPlatforms(PlatformsInfo& platforms)
|
||||
{
|
||||
if (!__initialized)
|
||||
initializeOpenCLDevices();
|
||||
|
||||
platforms.clear();
|
||||
|
||||
for (size_t id = 0; id < global_platforms.size(); ++id)
|
||||
@ -442,6 +663,9 @@ int getOpenCLPlatforms(PlatformsInfo& platforms)
|
||||
|
||||
int getOpenCLDevices(std::vector<const DeviceInfo*> &devices, int deviceType, const PlatformInfo* platform)
|
||||
{
|
||||
if (!__initialized)
|
||||
initializeOpenCLDevices();
|
||||
|
||||
devices.clear();
|
||||
|
||||
switch(deviceType)
|
||||
@ -461,7 +685,7 @@ int getOpenCLDevices(std::vector<const DeviceInfo*> &devices, int deviceType, co
|
||||
for (size_t id = 0; id < global_devices.size(); ++id)
|
||||
{
|
||||
DeviceInfoImpl& deviceInfo = global_devices[id];
|
||||
if (((int)deviceInfo.info.deviceType & deviceType) == deviceType)
|
||||
if (((int)deviceInfo.info.deviceType & deviceType) != 0)
|
||||
{
|
||||
devices.push_back(&deviceInfo.info);
|
||||
}
|
||||
@ -479,35 +703,14 @@ int getOpenCLDevices(std::vector<const DeviceInfo*> &devices, int deviceType, co
|
||||
}
|
||||
}
|
||||
|
||||
if (currentContext == NULL)
|
||||
{
|
||||
// select default device
|
||||
const DeviceInfo* selectedDevice = NULL;
|
||||
for (size_t i = 0; i < devices.size(); i++)
|
||||
{
|
||||
const DeviceInfo* dev = devices[i];
|
||||
if (dev->deviceType == CL_DEVICE_TYPE_GPU)
|
||||
{
|
||||
selectedDevice = dev;
|
||||
break;
|
||||
}
|
||||
else if (dev->deviceType == CL_DEVICE_TYPE_CPU && (selectedDevice == NULL))
|
||||
{
|
||||
selectedDevice = dev;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedDevice)
|
||||
{
|
||||
setDevice(selectedDevice);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)devices.size();
|
||||
}
|
||||
|
||||
void setDevice(const DeviceInfo* info)
|
||||
{
|
||||
if (!__deviceSelected)
|
||||
__deviceSelected = true;
|
||||
|
||||
ContextImpl::setContext(info);
|
||||
}
|
||||
|
||||
@ -518,14 +721,14 @@ bool supportsFeature(FEATURE_TYPE featureType)
|
||||
|
||||
struct __Module
|
||||
{
|
||||
__Module() { initializeOpenCLDevices(); }
|
||||
__Module() { /* moved to Context::getContext(): initializeOpenCLDevices(); */ }
|
||||
~__Module() { ContextImpl::cleanupContext(); }
|
||||
};
|
||||
static __Module __module;
|
||||
|
||||
|
||||
}//namespace ocl
|
||||
}//namespace cv
|
||||
} // namespace ocl
|
||||
} // namespace cv
|
||||
|
||||
|
||||
#if defined(WIN32) && defined(CVAPI_EXPORTS)
|
||||
|
@ -83,45 +83,52 @@ int main(int argc, char **argv)
|
||||
"{ p | platform | -1 | set platform id }"
|
||||
"{ d | device | 0 | set device id }";
|
||||
|
||||
CommandLineParser cmd(argc, argv, keys);
|
||||
if (cmd.get<bool>("help"))
|
||||
if (getenv("OPENCV_OPENCL_DEVICE") == NULL) // TODO Remove this after buildbot updates
|
||||
{
|
||||
cout << "Available options besides google test option:" << endl;
|
||||
cmd.printParams();
|
||||
return 0;
|
||||
}
|
||||
string type = cmd.get<string>("type");
|
||||
int pid = cmd.get<int>("platform");
|
||||
int device = cmd.get<int>("device");
|
||||
CommandLineParser cmd(argc, argv, keys);
|
||||
if (cmd.get<bool>("help"))
|
||||
{
|
||||
cout << "Available options besides google test option:" << endl;
|
||||
cmd.printParams();
|
||||
return 0;
|
||||
}
|
||||
string type = cmd.get<string>("type");
|
||||
int pid = cmd.get<int>("platform");
|
||||
int device = cmd.get<int>("device");
|
||||
|
||||
print_info();
|
||||
int flag = CVCL_DEVICE_TYPE_GPU;
|
||||
if(type == "cpu")
|
||||
{
|
||||
flag = CVCL_DEVICE_TYPE_CPU;
|
||||
print_info();
|
||||
int flag = CVCL_DEVICE_TYPE_GPU;
|
||||
if(type == "cpu")
|
||||
{
|
||||
flag = CVCL_DEVICE_TYPE_CPU;
|
||||
}
|
||||
|
||||
cv::ocl::PlatformsInfo platformsInfo;
|
||||
cv::ocl::getOpenCLPlatforms(platformsInfo);
|
||||
if (pid >= (int)platformsInfo.size())
|
||||
{
|
||||
std::cout << "platform is invalid\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cv::ocl::DevicesInfo devicesInfo;
|
||||
int devnums = cv::ocl::getOpenCLDevices(devicesInfo, flag, (pid < 0) ? NULL : platformsInfo[pid]);
|
||||
if (device < 0 || device >= devnums)
|
||||
{
|
||||
std::cout << "device/platform invalid\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cv::ocl::setDevice(devicesInfo[device]);
|
||||
}
|
||||
|
||||
cv::ocl::PlatformsInfo platformsInfo;
|
||||
cv::ocl::getOpenCLPlatforms(platformsInfo);
|
||||
if (pid >= (int)platformsInfo.size())
|
||||
{
|
||||
std::cout << "platform is invalid\n";
|
||||
return 1;
|
||||
}
|
||||
const DeviceInfo& deviceInfo = cv::ocl::Context::getContext()->getDeviceInfo();
|
||||
|
||||
cv::ocl::DevicesInfo devicesInfo;
|
||||
int devnums = cv::ocl::getOpenCLDevices(devicesInfo, flag, (pid < 0) ? NULL : platformsInfo[pid]);
|
||||
if (device < 0 || device >= devnums)
|
||||
{
|
||||
std::cout << "device/platform invalid\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cv::ocl::setDevice(devicesInfo[device]);
|
||||
|
||||
cout << "Device type: " << type << endl
|
||||
<< "Platform name: " << devicesInfo[device]->platform->platformName << endl
|
||||
<< "Device name: " << devicesInfo[device]->deviceName << endl;
|
||||
cout << "Device type: " << (deviceInfo.deviceType == CVCL_DEVICE_TYPE_CPU ?
|
||||
"CPU" :
|
||||
(deviceInfo.deviceType == CVCL_DEVICE_TYPE_GPU ? "GPU" : "unknown")) << endl
|
||||
<< "Platform name: " << deviceInfo.platform->platformName << endl
|
||||
<< "Device name: " << deviceInfo.deviceName << endl;
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user