NNPACK 移植与实验

发布于 2019-09-26 作者 风铃 36次 浏览 版块 前端

一、Ubuntu下使用:

1、克隆下载NNPACK

  1. git clone https://github.com/Maratyszcza/NNPACK.git

2、安装nijia,并编译

Install ninja build system

sudo apt-get install ninja-build || brew install ninja

Install PeachPy assembler and confu configuration system

[sudo] pip install --upgrade git+https://github.com/Maratyszcza/PeachPy

[sudo] pip install –upgrade git+https://github.com/Maratyszcza/confu

Then clone NNPACK, install dependencies, configure, and build

cd NNPACK
confu setup
python ./configure.py
ninja

3、链接的时候还需要用到pthread库,否在会遇到找不到实现函数。

  1. target_link_libraries(NNPACK libnnpack.a libpthreadpool.a pthread)  

需要加入pthread库,否这会报错。

4、测试代码

  1. #include <iostream>  
  2. #include "nnpack.h"  
  3. #include <ctime>  
  4. #include <vector>  
  5.   
  6. using namespace std;  
  7. float test_nnpack(){  
  8.     //init nnpack  
  9.     enum nnp_status init_status = nnp_initialize();  
  10.     if (init_status != nnp_status_success) {  
  11.         return 0;  
  12.     }  
  13.   
  14.     enum nnp_convolution_algorithm algorithm = nnp_convolution_algorithm_auto;  
  15.     enum nnp_convolution_transform_strategy strategy=nnp_convolution_transform_strategy_tuple_based;  
  16.     const size_t batch_size = 1;  
  17.     const size_t input_channels = 128;  
  18.     const size_t output_channels = 128;  
  19.     const struct nnp_padding input_padding = { 1, 1, 1, 1 };  
  20.     const struct nnp_size input_size ={ 256, 256};  
  21.     const struct nnp_size kernel_size = { 5, 5 };  
  22.     const struct  nnp_size stride={.width=2,.height=2};  
  23.     const struct nnp_size output_size = {  
  24.             .width = (input_padding.left + input_size.width + input_padding.right - kernel_size.width)/stride.width + 1,  
  25.             .height =(input_padding.top + input_size.height + input_padding.bottom - kernel_size.height)/stride.height  + 1  
  26.     };  
  27.   
  28.   
  29.     //malloc memory for input, kernel, output, bias  
  30.     float input = (float)malloc(batch_size * input_channels *input_size.height *input_size.width * sizeof(float));  
  31.     float kernel = (float)malloc(input_channels * output_channels * kernel_size.height * kernel_size.width * sizeof(float));  
  32.     float output = (float)malloc(batch_size* output_channels * output_size.height * output_size.width * sizeof(float));  
  33.     float bias = (float)malloc(output_channels * sizeof(float));  
  34.   
  35.     pthreadpool_t threadpool= nullptr;  
  36.   
  37.   
  38.     struct nnp_profile computation_profile;//use for compute time;  
  39.     //init input data  
  40.     int i,j;  
  41.     for(int c=0; c<input_channels;c++ ){  
  42.         for(i=0; i<input_size.height; i++){  
  43.             for(j=0; j<input_size.width; j++){  
  44.                 input[c*input_size.height*input_size.width+i*input_size.width+j] = (i*input_size.width+j)*0.1;  
  45.             }  
  46.         }  
  47.     }  
  48.   
  49.     //init kernel data  
  50.     for(int i=0; i<output_channels;i++ ){  
  51.         for(j=0; j<input_channels*kernel_size.height*kernel_size.width; j++){  
  52.             kernel[i*input_channels*kernel_size.height*kernel_size.width+j] = 0.1;  
  53.         }  
  54.     }  
  55.   
  56.     //init bias data  
  57.     for(int i=0; i<output_channels;i++ ){  
  58.         bias[i] = 1.0;  
  59.     }  
  60.   
  61.     //execute conv  
  62.   
  63.     for(int i=0;i<10;i++)  
  64.     {  
  65.         nnp_convolution_inference(algorithm,  
  66.                                   strategy,  
  67.                                   input_channels,  
  68.                                   output_channels,  
  69.                                   input_size,  
  70.                                   input_padding,  
  71.                                   kernel_size,  
  72.                                   stride,  
  73.                                   input,  
  74.                                   kernel,  
  75.                                   bias,  
  76.                                   output,  
  77.                                   threadpool,  
  78.                                   nullptr);  
  79.     }  
  80.   
  81.   std::vector<float>out;  
  82.     for(int i=0;i<output_channels*output_size.height*output_size.width;i++){  
  83.         out.push_back(output[i]);  
  84.     }  
  85.   
  86.     return conv_time_use;  
  87. }  
  88. int main() {  
  89.     cout << test_nnpack()<< endl;  
  90.     return 0;  
  91. }  

在mxnet、tiny-dnn中的引用方法:

  1. https://www.insight.io/github.com/dmlc/mxnet/blob/master/src/operator/nnpack/nnpack_convolution-inl.h  
  1. https://github.com/tiny-dnn/tiny-dnn/blob/master/tiny_dnn/core/kernels/conv2d_op_nnpack.h  

在tiny-dnn中,底层调用nnpack为啥只采用了一个线程,于是我测试了多线程的速度,经过测试发现nnpack的弱点,原来在于多线程:


二、android使用

1、添加ndk-build环境变量路径:

  1. export NDK_ROOT=/home/hjimce/Android/Sdk/ndk-bundle/  

cd到nnpack所在的目录,更改jni APP_PLATFORM := android-21

2、直接运行:

  1. ${NDK_ROOT}/ndk-build   

3、代码中引用cmake要指定相关的库文件:

  1. arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"  
  2. ndk {  
  3.     // Specifies the ABI configurations of your native  
  4.     // libraries Gradle should build and package with your APK.  
  5.     abiFilters 'x86','armeabi-v7a'  
  6. }  

手机速度测试:



修改:多线程时间测试不能使用time.clock(),可使用auto begin =std::chrono::high_resolution_clock::now();



收藏
暂无回复