You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

pylite.md 8.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. # PyLite
  2. Lite 的 python 接口提供更加方便灵活的使用 Lite 进行模型 Inference,满足如下条件的环境都可以使用:
  3. * OS 可以安装 [Python3](https://www.python.org/downloads/)
  4. * [BUILD_README](../../scripts/cmake-build/BUILD_README.md) 中支持推理编译的平台
  5. ## 安装
  6. ### whl 包安装
  7. 目前预编译发布的 Lite 的 whl 包详情如下:
  8. * 提供 Linux-x64(with CUDA)、windows-x64(with CUDA)、macos-x64(cpu only) 平台预编译包
  9. * 可以直接通过 pip3 安装。其他 OS-ARCH 的包,如有需要,可以 build from src 参考 [BUILD_README](../../scripts/cmake-build/BUILD_README.md)
  10. * 预编译包的构建流程可以参考 [BUILD_PYTHON_WHL_README.md](../../scripts/whl/BUILD_PYTHON_WHL_README.md)
  11. 开源版本: 预编译的包会随着 MegEngine 的发版发布,版本号和 MegEngine 保持一致,安装方式:
  12. ```shell
  13. python3 -m pip install --upgrade pip
  14. python3 -m pip install megengine -f https://megengine.org.cn/whl/mge.html
  15. ```
  16. 安装后, 就可以通过 import megenginelite 进行使用了
  17. ### develop 调试
  18. 开发模式下,可以使用 Cmake 编译出 lite 动态库,依然参考 [BUILD_README](../../scripts/cmake-build/BUILD_README.md):
  19. * Windows 平台,编译出来的 dll 是 lite_shared_whl.dll
  20. * None Windows 平台,编译出来的 so 是 liblite_shared_whl.so
  21. * 编译上述库的步骤:
  22. * clone 代码
  23. ```shell
  24. 开源版本:git clone git@github.com:MegEngine/MegEngine.git
  25. ```
  26. * 编译准备
  27. ```shell
  28. 开源版本: cd MegEngine
  29. bash ./third_party/prepare.sh
  30. ```
  31. * 编译 HOST 版本:
  32. ```shell
  33. ./scripts/cmake-build/host_build.sh
  34. ```
  35. * 编译 HOST 版本 (with CUDA):
  36. ```shell
  37. ./scripts/cmake-build/host_build.sh -c
  38. ```
  39. * 编译 Android 平台:
  40. ```shell
  41. scripts/cmake-build/cross_build_android_arm_inference.sh
  42. ```
  43. * 其他OS-ARCH可参考 [BUILD_README](../../scripts/cmake-build/BUILD_README.md)
  44. * 编译完成之后,相应的库可在 build_dir 下找到, 这里假设它的目录是LITE_LIB_PATH=path_of_lite_shared_whl
  45. * 开始使用 megenginelite
  46. ```shell
  47. export LITE_LIB_PATH=path_of_lite_shared_whl
  48. export PYTHONPATH=lite/pylite:$PYTHONPATH
  49. 然后就可以 import megenginelite 进行使用了
  50. ```
  51. ## python3 中使用 megenginelite
  52. Lite 的 python3 接口是对其 C/C++ 接口的一层封装,他们使用的模型都是相同的模型格式。megenginelite 提供两种数据接口,分别是 LiteTensor 和 LiteNetwork。
  53. ### LiteTensor
  54. LiteTensor 提供了用户对数据的操作接口,提供了接口包括:
  55. * fill_zero: 将 tensor 的内存设置为全0
  56. * share_memory_with: 可以和其他 LiteTensor 的共享内存
  57. * copy_from: 从其他 LiteTensor 中 copy 数据到自身内存中
  58. * reshape: 改变该 LiteTensor 的 shape,内存数据保持不变
  59. * slice: 对该 LiteTensor 中的数据进行切片,需要分别指定每一维切片的 start,end,和 step。
  60. * set_data_by_share: 调用之后使得该 LiteTensor 中的内存共享自输入的 array 的内存,输入的 array 必须是numpy 的 ndarray,并且 tensor 在 CPU 上
  61. * set_data_by_copy: 该 LiteTensor 将会从输入的 data 中 copy 数据,data 可以是 list 和 numpy 的 ndarray,需要保证 data 的数据量不超过 tensor 的容量,tensor 在 CPU 上
  62. * to_numpy: 将该 LiteTensor 中数据 copy 到 numpy 的 array 中,返回给用户,如果是非连续的 LiteTensor,如 slice 出来的,将 copy 到连续的 numpy array 中,该接口主要数为了 debug,有性能问题。
  63. #### 使用 example
  64. * LiteTensor 设置数据 example
  65. ```
  66. def test_tensor_set_data():
  67. layout = LiteLayout([2, 16], "int8")
  68. tensor = LiteTensor(layout)
  69. assert tensor.nbytes == 2 * 16
  70. data = [i for i in range(32)]
  71. tensor.set_data_by_copy(data)
  72. real_data = tensor.to_numpy()
  73. for i in range(32):
  74. assert real_data[i // 16][i % 16] == i
  75. arr = np.ones([2, 16], "int8")
  76. tensor.set_data_by_copy(arr)
  77. real_data = tensor.to_numpy()
  78. for i in range(32):
  79. assert real_data[i // 16][i % 16] == 1
  80. for i in range(32):
  81. arr[i // 16][i % 16] = i
  82. tensor.set_data_by_share(arr)
  83. real_data = tensor.to_numpy()
  84. for i in range(32):
  85. assert real_data[i // 16][i % 16] == i
  86. arr[0][8] = 100
  87. arr[1][3] = 20
  88. real_data = tensor.to_numpy()
  89. assert real_data[0][8] == 100
  90. assert real_data[1][3] == 20
  91. ```
  92. * tensor 共享内存 example
  93. ```python
  94. def test_tensor_share_memory_with():
  95. layout = LiteLayout([4, 32], "int16")
  96. tensor = LiteTensor(layout)
  97. assert tensor.nbytes == 4 * 32 * 2
  98. arr = np.ones([4, 32], "int16")
  99. for i in range(128):
  100. arr[i // 32][i % 32] = i
  101. tensor.set_data_by_share(arr)
  102. real_data = tensor.to_numpy()
  103. for i in range(128):
  104. assert real_data[i // 32][i % 32] == i
  105. tensor2 = LiteTensor(layout)
  106. tensor2.share_memory_with(tensor)
  107. real_data = tensor.to_numpy()
  108. real_data2 = tensor2.to_numpy()
  109. for i in range(128):
  110. assert real_data[i // 32][i % 32] == i
  111. assert real_data2[i // 32][i % 32] == i
  112. arr[1][18] = 5
  113. arr[3][7] = 345
  114. real_data = tensor2.to_numpy()
  115. assert real_data[1][18] == 5
  116. assert real_data[3][7] == 345
  117. ```
  118. 更多的使用可以参考 pylite 中 test/test_tensor.py 中的使用
  119. ### LiteNetwork
  120. LiteNetwork 主要为用户提供模型载入,运行等功能。使用的模型见 lite 的 readme 中关于模型的部分
  121. * CPU 基本模型载入运行的 example
  122. ```
  123. def test_network_basic():
  124. source_dir = os.getenv("LITE_TEST_RESOURCE")
  125. input_data_path = os.path.join(source_dir, "input_data.npy")
  126. # read input to input_data
  127. input_data = np.load(input_data_path)
  128. model_path = os.path.join(source_dir, "shufflenet.mge")
  129. network = LiteNetwork()
  130. network.load(model_path)
  131. input_name = network.get_input_name(0)
  132. input_tensor = network.get_io_tensor(input_name)
  133. output_name = network.get_output_name(0)
  134. output_tensor = network.get_io_tensor(output_name)
  135. assert input_tensor.layout.shapes[0] == 1
  136. assert input_tensor.layout.shapes[1] == 3
  137. assert input_tensor.layout.shapes[2] == 224
  138. assert input_tensor.layout.shapes[3] == 224
  139. assert input_tensor.layout.data_type == LiteDataType.LITE_FLOAT
  140. assert input_tensor.layout.ndim == 4
  141. # copy input data to input_tensor of the network
  142. input_tensor.set_data_by_copy(input_data)
  143. for i in range(3):
  144. network.forward()
  145. network.wait()
  146. output_data = output_tensor.to_numpy()
  147. print('shufflenet output max={}, sum={}'.format(output_data.max(), output_data.sum()))
  148. ```
  149. * CUDA 上使用 device 内存作为模型输入,需要在构造 network 候配置 config 和 IO 信息
  150. ```
  151. def test_network_device_IO():
  152. source_dir = os.getenv("LITE_TEST_RESOURCE")
  153. input_data_path = os.path.join(source_dir, "input_data.npy")
  154. model_path = os.path.join(source_dir, "shufflenet.mge")
  155. # read input to input_data
  156. input_data = np.load(input_data_path)
  157. input_layout = LiteLayout([1, 3, 224, 224])
  158. host_input_data = LiteTensor(layout=input_layout)
  159. host_input_data.set_data_by_share(input_data)
  160. dev_input_data = LiteTensor(layout=input_layout, device_type=LiteDeviceType.LITE_CUDA)
  161. dev_input_data.copy_from(host_input_data)
  162. # construct LiteOption
  163. options = LiteOptions()
  164. options.weight_preprocess = 1
  165. options.var_sanity_check_first_run = 0
  166. net_config = LiteConfig(device_type=LiteDeviceType.LITE_CUDA, option=options)
  167. # constuct LiteIO, is_host=False means the input tensor will use device memory
  168. input_io = LiteIO("data", is_host=False)
  169. ios = LiteNetworkIO()
  170. ios.add_input(input_io)
  171. network = LiteNetwork(config=net_config, io=ios)
  172. network.load(model_path)
  173. input_name = network.get_input_name(0)
  174. dev_input_tensor = network.get_io_tensor(input_name)
  175. output_name = network.get_output_name(0)
  176. output_tensor = network.get_io_tensor(output_name)
  177. # copy input data to input_tensor of the network
  178. dev_input_tensor.share_memory_with(dev_input_data)
  179. for i in range(3):
  180. network.forward()
  181. network.wait()
  182. output_data = output_tensor.to_numpy()
  183. print('shufflenet output max={}, sum={}'.format(output_data.max(), output_data.sum()))
  184. ```
  185. 更多的使用可以参考 pylite 中 test/test_network.py 和 test/test_network_cuda.py 中的使用

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台