打开微信,使用扫一扫进入页面后,点击右上角菜单,
点击“发送给朋友”或“分享到朋友圈”完成分享
背景
寒武纪提供的离线模型部署的接口是c++形式的,没有提供python的接口形式。对于某些原本是python构建的应用,无法直接调用cnrt的接口去推理,需要把cnrt的接口封装成python能够调用的接口。以下是python调cnrt接口的一种实现方式。
实现原理
通过python的ctypes库来实现。cnrt的接口比较多,涉及设备管理、内存管理、上下文管理、模型信息管理、任务调度管理等接口。如果全部暴露到python接口层面,增加了大量的工作量。这些接口可以进行适当的组合封装,按需暴露必要的高层语义的接口,不仅节省了大量的接口适配适配的工作,还可以让python应用调用推理的流程简化很多。
def test_api2(api_lib, offlinemodel, img_file): #1. init handle handle = api_lib.cnpyInit(offlinemodel) #2. prepare input img = cv.imread(img_file) img_resize = cv.resize(img, (224, 224)) img2 = img_resize - (104, 117, 124) img3 = img2.astype(np.float32) data = np.asarray(img3, dtype=np.float32) input = data.ctypes.data_as(ctypes.c_void_p) #3. inference api_lib.cnpyInference.restype = POINTER(POINTER(c_float)) output = api_lib.cnpyInference(handle, input) #4. postprocess for i in range(1000): if output[0][i] > 0.1: print output.contents[i] if __name__ == "__main__": ll = ctypes.cdll.LoadLibrary api_lib = ll("../../lib/libcnrtapi.so") offlinemodel = "../../testcase/input/models/resnet50.cambricon".encode() image_file = "../../testcase/input/image/0001.jpg" # test_api(api_lib, offlinemodel, image_file) test_api2(api_lib, offlinemodel, image_file)
接口封装的核心在于c++和python之间的数据结构的转换,因为输入一般情况下是一个,输出可能有多个,所以输入的类型是一级指针(void*),输出是个二级指针(float**)。通过data.ctypes.data_as(ctypes.c_void_p)表达出输入是void*,通过api_lib.cnpyInference.restype = POINTER(POINTER(c_float)) 指示输出是float**。
代码实现
热门帖子
精华帖子