在<学习OpenVINO笔记之Inference Engine Device Query API>中的查询设备用例中,有使用到查看当前有哪些设备可以上线接口GetAvailableDevices()函数,通过该接口流程可以查看对当前已上线的设备是怎么管理的,对后面移植openvino非常重要,过下源码对该流程进行分析。

Core::GetAvailableDevices()

对外提供的接口是在Core类中GetAvailableDevices()API,代码如下:

首先是调用Impl类中的GetListOfDevicesInRegistry()接口,获取到已知的注册的设备类型

pluginRegistry类为plugins.xml文件中注册的设备类型,对每个设备类型进行单独轮询调用GetMetric接口。

Core::GetMetric

GetMetric()获取该类型设备实际能力

调用的是Engine中的Engine::GetMetric方法

Engine::GetMetric

Engine::GetMetric()函数处理如下

最后调用的是_metrics,而

_metrics指向的是MyriadMetrics类地址:

整个调用过程太繁琐,最后使用的Mvnc类中的接口

最后调用ncAvailableDevices接口,获取到当前上线的设备数量,该接口属于第三方库movidius中API.

ncAvailableDevices

接下来就要涉及到movidius sdk host端源码,ncAvailableDevices为获取到当前上线的movidius数量:

最大支持的数量为NC_MAX_DEVICES 32个

#define NC_MAX_DEVICES         (32)

设置当前获取到的协议类型为X_LINK_ANY_PROTOCOL,支持任何类型

开始涉及到X_LINK协议,该协议是将不同的硬件接口统一封装到X_LINK中,支持USB, PCIE,IPC等类型的接口,X_LINK模块负责提供整个的统一访问movidius平台

最后是调用XLinkPlatformFindArrayOfDevicesNames接口,该接口支持不同的协议类型

xLinkPlatformErrorCode_t XLinkPlatformFindArrayOfDevicesNames(XLinkDeviceState_t state,const deviceDesc_t in_deviceRequirements,deviceDesc_t* out_foundDevice,const unsigned int devicesArraySize,unsigned int *out_amountOfFoundDevices) {memset(out_foundDevice, 0, sizeof(deviceDesc_t) * devicesArraySize);unsigned int usb_index = 0;unsigned int pcie_index = 0;unsigned int both_protocol_index = 0;// TODO Handle possible errorsswitch (in_deviceRequirements.protocol){case X_LINK_USB_CDC:case X_LINK_USB_VSC:while(getUSBDeviceName(usb_index, state, in_deviceRequirements, &out_foundDevice[usb_index]) ==X_LINK_PLATFORM_SUCCESS) {++usb_index;}*out_amountOfFoundDevices = usb_index;return X_LINK_PLATFORM_SUCCESS;case X_LINK_PCIE:while(getPCIeDeviceName(pcie_index, state, in_deviceRequirements, &out_foundDevice[pcie_index]) ==X_LINK_PLATFORM_SUCCESS) {++pcie_index;}*out_amountOfFoundDevices = pcie_index;return X_LINK_PLATFORM_SUCCESS;case X_LINK_ANY_PROTOCOL:while(getUSBDeviceName(usb_index, state, in_deviceRequirements,&out_foundDevice[both_protocol_index]) ==X_LINK_PLATFORM_SUCCESS) {++usb_index;++both_protocol_index;}while(getPCIeDeviceName(pcie_index, state, in_deviceRequirements,&out_foundDevice[both_protocol_index]) ==X_LINK_PLATFORM_SUCCESS) {++pcie_index;++both_protocol_index;}*out_amountOfFoundDevices = both_protocol_index;return X_LINK_PLATFORM_SUCCESS;default:mvLog(MVLOG_WARN, "Unknown protocol");return X_LINK_PLATFORM_DEVICE_NOT_FOUND;}
}

其中X_LINK_ANY_PROTOCOL为即支持USB,也支持usb接口:

getUSBDeviceName

getUSBDeviceName()为查找usb接口下的所有设备,其驱动接口使用的是libusb

static xLinkPlatformErrorCode_t getUSBDeviceName(int index,XLinkDeviceState_t state,const deviceDesc_t in_deviceRequirements,deviceDesc_t* out_foundDevice) {ASSERT_X_LINK_PLATFORM(index >= 0);ASSERT_X_LINK_PLATFORM(out_foundDevice);int vid = AUTO_VID;int pid = AUTO_PID;char name[XLINK_MAX_NAME_SIZE] = {};int searchByName = 0;if (strlen(in_deviceRequirements.name) > 0) {searchByName = 1;mv_strcpy(name, XLINK_MAX_NAME_SIZE, in_deviceRequirements.name);}// Set PIDif (state == X_LINK_BOOTED) {if (in_deviceRequirements.platform != X_LINK_ANY_PLATFORM) {mvLog(MVLOG_WARN, "Search specific platform for booted device unavailable");return X_LINK_PLATFORM_ERROR;}pid = DEFAULT_OPENPID;} else {if (searchByName) {pid = get_pid_by_name(in_deviceRequirements.name);} else {pid = XLinkPlatformToPid(in_deviceRequirements.platform, state);}}#if (!defined(_WIN32) && !defined(_WIN64))uint16_t  bcdusb = -1;usbBootError_t rc = usb_find_device_with_bcd(index, name, XLINK_MAX_NAME_SIZE, 0, vid, pid, &bcdusb);
#elseusbBootError_t rc = usb_find_device(index, name, XLINK_MAX_NAME_SIZE, 0, vid, pid);
#endifxLinkPlatformErrorCode_t xLinkRc = parseUsbBootError(rc);if(xLinkRc == X_LINK_PLATFORM_SUCCESS){mv_strcpy(out_foundDevice->name, XLINK_MAX_NAME_SIZE, name);out_foundDevice->protocol = X_LINK_USB_VSC;out_foundDevice->platform = XLinkPlatformPidToPlatform(get_pid_by_name(name));}return xLinkRc;
}

in_deviceRequirements.name没有指定,为查找到所有的usb下设备,unbutun平台下使用usb_find_device_with_bcd接口


/*** @brief Find usb device address* @param input_addr  Device name (address) which would be returned. If not empty, we will try to*                  find device with this name** @details* Find any device (device = 0):* <br> 1) Any myriad device:                    vid = AUTO_VID & pid = AUTO_PID* <br> 2) Any not booted myriad device:         vid = AUTO_VID & pid = AUTO_UNBOOTED_PID* <br> 3) Any booted myriad device:             vid = AUTO_VID & pid = DEFAULT_OPENPID* <br> 4) Specific Myriad 2 or Myriad X device: vid = AUTO_VID & pid = DEFAULT_UNBOOTPID_2485 or DEFAULT_UNBOOTPID_2150* <br><br> Find specific device (device != 0):* <br> device arg should be not null, search by addr (name) and return device struct** @note* Index can be used to iterate through all connected myriad devices and save their names.* It will loop only over suitable devices specified by vid and pid*/
usbBootError_t usb_find_device_with_bcd(unsigned idx, char *input_addr,unsigned addrsize, void **device, int vid, int pid, uint16_t* bcdusb) {if (pthread_mutex_lock(&globalMutex)) {fprintf(stderr, "Mutex lock failed\n");return USB_BOOT_ERROR;}int searchByName = 0;static libusb_device **devs = NULL;libusb_device *dev = NULL;struct libusb_device_descriptor desc;int count = 0;size_t i;int res;if (!initialized) {if (usb_loglevel)fprintf(stderr, "Library has not been initialized when loaded\n");if (pthread_mutex_unlock(&globalMutex)) {fprintf(stderr, "Mutex unlock failed\n");}return USB_BOOT_ERROR;}if (strlen(input_addr) > 1) {searchByName = 1;}// Update device list if empty or if indx 0if (!devs || idx == 0) {if (devs) {libusb_free_device_list(devs, 1);devs = 0;}if ((res = libusb_get_device_list(NULL, &devs)) < 0) {if (usb_loglevel)fprintf(stderr, "Unable to get USB device list: %s\n", libusb_strerror(res));if (pthread_mutex_unlock(&globalMutex)) {fprintf(stderr, "Mutex unlock failed\n");}return USB_BOOT_ERROR;}}// Loop over all usb devices, increase count only if myriad devicei = 0;while ((dev = devs[i++]) != NULL) {if ((res = libusb_get_device_descriptor(dev, &desc)) < 0) {if (usb_loglevel)fprintf(stderr, "Unable to get USB device descriptor: %s\n", libusb_strerror(res));continue;}// If found device have the same id and vid as inputif ( (desc.idVendor == vid && desc.idProduct == pid)// Any myriad device|| (vid == AUTO_VID && pid == AUTO_PID&& isMyriadDevice(desc.idVendor, desc.idProduct))// Any not booted myriad device|| (vid == AUTO_VID && (pid == AUTO_UNBOOTED_PID)&& isNotBootedMyriadDevice(desc.idVendor, desc.idProduct))// Any not booted with specific pid|| (vid == AUTO_VID && pid == desc.idProduct&& isNotBootedMyriadDevice(desc.idVendor, desc.idProduct))// Any booted device|| (vid == AUTO_VID && pid == DEFAULT_OPENPID&& isBootedMyriadDevice(desc.idVendor, desc.idProduct)) ){if (device) {const char *dev_addr = gen_addr(dev, get_pid_by_name(input_addr));if (!strcmp(dev_addr, input_addr)) {if (usb_loglevel > 1) {fprintf(stderr, "Found Address: %s - VID/PID %04x:%04x\n",input_addr, desc.idVendor, desc.idProduct);}libusb_ref_device(dev);libusb_free_device_list(devs, 1);if (bcdusb)*bcdusb = desc.bcdUSB;*device = dev;devs = 0;if (pthread_mutex_unlock(&globalMutex)) {fprintf(stderr, "Mutex unlock failed\n");}return USB_BOOT_SUCCESS;}} else if (searchByName) {const char *dev_addr = gen_addr(dev, desc.idProduct);// If the same add as inputif (!strcmp(dev_addr, input_addr)) {if (usb_loglevel > 1) {fprintf(stderr, "Found Address: %s - VID/PID %04x:%04x\n",input_addr, desc.idVendor, desc.idProduct);}if (pthread_mutex_unlock(&globalMutex)) {fprintf(stderr, "Mutex unlock failed\n");}return USB_BOOT_SUCCESS;}} else if (idx == count) {const char *caddr = gen_addr(dev, desc.idProduct);if (usb_loglevel > 1)fprintf(stderr, "Device %d Address: %s - VID/PID %04x:%04x\n",idx, caddr, desc.idVendor, desc.idProduct);mv_strncpy(input_addr, addrsize, caddr, addrsize - 1);if (pthread_mutex_unlock(&globalMutex)) {fprintf(stderr, "Mutex unlock failed\n");}return USB_BOOT_SUCCESS;}count++;}}libusb_free_device_list(devs, 1);devs = 0;if (pthread_mutex_unlock(&globalMutex)) {fprintf(stderr, "Mutex unlock failed\n");}return USB_BOOT_DEVICE_NOT_FOUND;
}

主要使用的是libusb 驱动接口获取设备特性。

getPCIeDeviceName

getPCIeDeviceName()接口

static xLinkPlatformErrorCode_t getPCIeDeviceName(int index,XLinkDeviceState_t state,const deviceDesc_t in_deviceRequirements,deviceDesc_t* out_foundDevice) {ASSERT_X_LINK_PLATFORM(index >= 0);ASSERT_X_LINK_PLATFORM(out_foundDevice);ASSERT_X_LINK_PLATFORM(in_deviceRequirements.platform != X_LINK_MYRIAD_2);char name[XLINK_MAX_NAME_SIZE] = {};if (strlen(in_deviceRequirements.name) > 0) {mv_strcpy(name, XLINK_MAX_NAME_SIZE, in_deviceRequirements.name);}pcieHostError_t rc = pcie_find_device_port(index, name, XLINK_MAX_NAME_SIZE, XLinkStateToPciePlatformState(state));xLinkPlatformErrorCode_t xLinkRc = parsePCIeHostError(rc);if(xLinkRc == X_LINK_PLATFORM_SUCCESS){mv_strcpy(out_foundDevice->name, XLINK_MAX_NAME_SIZE, name);out_foundDevice->protocol = X_LINK_PCIE;out_foundDevice->platform = X_LINK_MYRIAD_X;}return xLinkRc;
}

最终调用pcie_find_device_port接口


pcieHostError_t pcie_find_device_port(int index, char* port_name, int name_length, const pciePlatformState_t requiredState) {ASSERT_X_LINK_PLATFORM(port_name);ASSERT_X_LINK_PLATFORM(index >= 0);ASSERT_X_LINK_PLATFORM(name_length > 0);pcieHostError_t rc = PCIE_HOST_DEVICE_NOT_FOUND;char found_device[XLINK_MAX_NAME_SIZE] = { 0 };pciePlatformState_t platformState;#if (defined(_WIN32) || defined(_WIN64))int amoutOfMyriadPCIeDevices = pci_count_devices(PCIE_VENDOR_ID, PCIE_DEVICE_ID);if (amoutOfMyriadPCIeDevices == 0)return PCIE_HOST_DEVICE_NOT_FOUND;int amountOfSuitableDevices = 0;int deviceCount = 0;while (deviceCount < amoutOfMyriadPCIeDevices) {snprintf(found_device, XLINK_MAX_NAME_SIZE, "%s%d", "\\\\.\\mxlink", deviceCount);// Get state of deviceif (pcie_get_device_state(found_device, &platformState) != 0) {return PCIE_HOST_ERROR;   // Get device state step failed}// Found device suits requested stateif (platformState == requiredState || requiredState == PCIE_PLATFORM_ANY_STATE) {// If port_name is specified, we search for specific deviceif (strnlen(port_name, name_length) > 1 &&strncmp(port_name, found_device, name_length) == 0) {rc = PCIE_HOST_SUCCESS;break;// Trying to find device which suits requirements and index}else if (amountOfSuitableDevices == index) {mv_strncpy(port_name, name_length,found_device, XLINK_MAX_NAME_SIZE - 1);rc = PCIE_HOST_SUCCESS;break;}++amountOfSuitableDevices;}++deviceCount;}return rc;
#elsestruct dirent *entry;DIR *dp;dp = opendir("/sys/class/mxlk/");if (dp == NULL) {return PCIE_HOST_DRIVER_NOT_LOADED;}// All entries in this (virtual) directory are generated when the driver// is loaded, and correspond 1:1 to entries in /dev/int device_cnt = 0;while((entry = readdir(dp))) {// Compare the beginning of the name to make sure it is a device nameif (strncmp(entry->d_name, "mxlk", 4) == 0){// Save namesnprintf(found_device, name_length, "/dev/%s", entry->d_name);// Get state of deviceif (pcie_get_device_state(found_device, &platformState) != 0) {closedir(dp);return PCIE_HOST_ERROR;   // Get device state step failed}// Found device suits requested stateif (platformState == requiredState || requiredState == PCIE_PLATFORM_ANY_STATE) {// If port_name is specified, we search for specific deviceif (strnlen(port_name, name_length) > 1 &&strncmp(port_name, found_device, name_length) == 0) {rc = PCIE_HOST_SUCCESS;break;// Trying to find device which suits requirements and index} else if (device_cnt == index){mv_strncpy(port_name, name_length,found_device, XLINK_MAX_NAME_SIZE - 1);rc = PCIE_HOST_SUCCESS;break;}++device_cnt;}}}closedir(dp);return rc;
#endif  // (!defined(_WIN32) && !defined(_WIN64))
}

上述是整个GetAvailableDevices工作流程,七拐八绕,比较麻烦

其他特性获取

其他特性的获取同样最后都是调用MyriadMetrics, 其实出了获取设备name ,id,其他特性都是写死的

//------------------------------------------------------------------------------
// Implementation of methods of class MyriadMetrics
//------------------------------------------------------------------------------MyriadMetrics::MyriadMetrics() {_supportedMetrics = {METRIC_KEY(AVAILABLE_DEVICES),METRIC_KEY(FULL_DEVICE_NAME),METRIC_KEY(SUPPORTED_METRICS),METRIC_KEY(SUPPORTED_CONFIG_KEYS),METRIC_KEY(OPTIMIZATION_CAPABILITIES),METRIC_KEY(RANGE_FOR_ASYNC_INFER_REQUESTS)};_supportedConfigKeys = {KEY_VPU_HW_STAGES_OPTIMIZATION,KEY_VPU_LOG_LEVEL,KEY_VPU_PRINT_RECEIVE_TENSOR_TIME,KEY_VPU_NETWORK_CONFIG,KEY_VPU_COMPUTE_LAYOUT,KEY_VPU_CUSTOM_LAYERS,KEY_VPU_IGNORE_IR_STATISTIC,KEY_VPU_MYRIAD_FORCE_RESET,KEY_VPU_MYRIAD_PLATFORM,KEY_EXCLUSIVE_ASYNC_REQUESTS,KEY_LOG_LEVEL,KEY_PERF_COUNT,KEY_CONFIG_FILE,KEY_DEVICE_ID};_optimizationCapabilities = { METRIC_VALUE(FP16) };_rangeForAsyncInferRequests = RangeType(3, 6, 1);_idToDeviceFullNameMap = {{"5", "Intel Movidius Myriad 2 VPU"},{"8", "Intel Movidius Myriad X VPU"},};
}std::vector<std::string> MyriadMetrics::AvailableDevicesNames(const std::shared_ptr<IMvnc> &mvnc,const std::vector<DevicePtr> &devicePool) const {std::vector<std::string> availableDevices;auto unbootedDevices = mvnc->AvailableDevicesNames();availableDevices.insert(availableDevices.begin(),unbootedDevices.begin(), unbootedDevices.end());for (auto & device : devicePool) {availableDevices.push_back(device->_name);}std::sort(availableDevices.begin(), availableDevices.end());return availableDevices;
}std::string MyriadMetrics::FullName(std::string deviceName) const {std::string nameDelimiter("-ma");unsigned int indexLenght = 4;unsigned int placeOfTypeId = 2;auto indexStr = deviceName;indexStr.erase(0, indexStr.find(nameDelimiter) + nameDelimiter.length());if (indexLenght != indexStr.length()) {return deviceName;} else {auto myriadId = std::string(1, indexStr[placeOfTypeId]);if (_idToDeviceFullNameMap.count(myriadId)) {return _idToDeviceFullNameMap.at(myriadId);}}return deviceName;
}const std::vector<std::string>& MyriadMetrics::SupportedMetrics() const {return _supportedMetrics;
}const std::vector<std::string>& MyriadMetrics::SupportedConfigKeys() const {return _supportedConfigKeys;
}const std::vector<std::string>& MyriadMetrics::OptimizationCapabilities() const {return _optimizationCapabilities;
}RangeType MyriadMetrics::RangeForAsyncInferRequests(const std::map<std::string, std::string>& config) const {auto throughput_streams_str = config.find(KEY_VPU_MYRIAD_THROUGHPUT_STREAMS);if (throughput_streams_str != config.end()) {try {int throughput_streams = std::stoi(throughput_streams_str->second);if (throughput_streams > 0) {return RangeType(throughput_streams+1, throughput_streams*3, 1);}}catch(...) {THROW_IE_EXCEPTION << "Invalid config value for VPU_MYRIAD_THROUGHPUT_STREAMS, can't cast to int";}}return _rangeForAsyncInferRequests;
}

OpenVINO Inference Engine之GetAvailableDevices相关推荐

  1. OpenVINO Inference Engine之custom Layer自定义算法(VPU版本)

    OpenVINO不仅支持广泛的已知深度学习架构(Caff,TensorFlow等),还支持用户自定义CNN 算法,拥有良好的可扩展性.要使用用户自定义功能就要使用到Inference Engine K ...

  2. OpenVINO Inference Engine之LoadNetwork

    在<OpenVINO InferenceEngine之Core类>之中只是简单了介绍了一下loadNetwork的整个流程,还没有涉及到真正的加载动作.如上文中所示,在加载网络之前需要首先 ...

  3. 学习OpenVINO笔记之Inference Engine Device Query API

    Device Query API是OpenVINO在R2版本时整合引入新的API,主要可以用来查询不同设备属性和配置参数,可以让开发者更加了解设备配置,使用起来更加方便.R2 API与 R1版本相比较 ...

  4. 学习OpenVINO笔记之Inference Engine

    Inference Engine是OpenVINO具体实施单元,支持CPU,GPU,FPGA,Movidius,GNA等因特尔开发的硬件平台,并提供可操作API,API为C++接口,也支持python ...

  5. JointDNN: An Effificient Training and Inference Engine for Intelligent Mobile Cloud Computing Servic

    题目:JointDNN: An Effificient Training and Inference Engine for Intelligent Mobile Cloud Computing Ser ...

  6. [论文阅读] EIE: Efficient Inference Engine on Compressed Neural Network

    这是收录于ISCA16(International Symposium on Computer Architecture). 其是Deep Compression以及DSD的系列篇,其在Deep Co ...

  7. 韩松EIE:Efficient Inference Engine on Compressed Deep Neural Network论文详解

    EIE为韩松博士在ISCA 2016上的论文.实现了压缩的稀疏神经网络的硬件加速.与其近似方法的ESE获得了FPGA2017的最佳论文. 目录 一.背景与介绍 1.1 Motivation 1.2 前 ...

  8. 韩松 EIE: Efficient Inference Engine on Compressed Deep Neural Network论文详解

    EIE为韩松博士在ISCA 2016上的论文,实现了压缩的稀疏神经网络的硬件加速. 与其近似方法的ESE获得了FPGA2017的最佳论文. 背景与介绍 最新的DNN模型都是运算密集型和存储密集型,难以 ...

  9. OpenVINO示例介绍

    接着前面系列博客来讲,我们知道学东西应该先从官网的示例来着手,循序渐进,这是一个很好的学习方法.有两处例子: 第一处,OpenVINO安装路径下的例子,在用Using Installer安装OpenV ...

最新文章

  1. 万众赋能工业4.0:三一数据应用大赛圆满落幕
  2. matlab之unwrap函数
  3. GDCM:DICOM文件转储ADAC文件的测试程序
  4. 前端学习(586):在元素中动态添加类与伪类
  5. 如何在Windows中的命令提示符下删除特定目录中的文件/子文件夹
  6. Oracle fgs(精细审计)使用
  7. nvidia tesla k40
  8. 计算机硬盘格式化了如何恢复出厂设置,怎么把电脑格式化?
  9. arm android开发板推荐,arm7开发板推荐 最新arm开发板了解
  10. 这一年,我所阐释的Linux哲学
  11. 电脑网络连接怎么设置
  12. JAVAScript:mobile端,基于transform-origin和tranform(scale),实现表格缩放
  13. 【线性代数】深入理解矩阵乘法、对称矩阵、正定矩阵
  14. 韩松EIE:Efficient Inference Engine on Compressed Deep Neural Network论文详解
  15. 电大本科计算机上机考试题库,国家开放大学电大计算机操作考试题题库及答案...
  16. anki服务端存储迁移
  17. 如何做好项目沟通管理的工作
  18. 电脑c盘不够用怎么扩容,磁盘c怎么扩展
  19. python 笔记--同时输入两个数字
  20. 西门子PLC与Profinet工业以太网RFID读写器|读卡器的编程与配置说明

热门文章

  1. 修改Yarn的全局安装和缓存位置
  2. 【插件发布】JAVA微服务框架,Jeecg-P3-Biz-OA 1.0.0 插件开源发布
  3. 移动页面自适应手机屏幕宽度HTML5开发
  4. Python3.7 Scrapy安装(Windows)
  5. 学习react的心路历程(一)
  6. openstack kvm 虚拟机磁盘差异衍生
  7. 【CSS+HTML】关于字体的说明
  8. Android -- App生成快捷方式
  9. Delphi发送邮件...
  10. 大型数据库的设计原则与开发技巧