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.1 kB

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

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