NNPACK详解

NNPACK详解
一:NNPACK简介
NNPACK由facebook开发,是一个加速神经网络计算的加速包,NNPACK可以在多核CPU平台上提高卷积层计算性能NNPACK采用的快速卷积算法是基于Fourier transform 和 Winograd transform算法


二:前向计算的性能
如下图(Intel Core i7 6700K vs BVLC Caffe master branch)
Library Caffe NNPACK NNPACK NNPACK
Algorithm im2col + sgemm FFT-8x8 FFT-16x16 Winograd F(6x6, 3x3)
AlexNet:conv2 315 ms 129 ms 86 ms N/A
AlexNet:conv3 182 ms 87 ms 44 ms 70 ms
AlexNet:conv4 264 ms 109 ms 56 ms 89 ms
AlexNet:conv5 177 ms 77 ms 40 ms 64 ms
VGG-A:conv1 255 ms 303 ms 260 ms 404 ms
VGG-A:conv2 902 ms 369 ms 267 ms 372 ms
VGG-A:conv3.1 566 ms 308 ms 185 ms 279 ms
VGG-A:conv3.2 1091 ms 517 ms 309 ms 463 ms
VGG-A:conv4.1 432 ms 228 ms 149 ms 188 ms
VGG-A:conv4.2 842 ms 402 ms 264 ms 329 ms
VGG-A:conv5 292 ms 141 ms 83 ms 114 ms
OverFeat:conv2 424 ms 158 ms 73 ms N/A
OverFeat:conv3 250 ms 69 ms 74 ms 54 ms
OverFeat:conv4 927 ms 256 ms 272 ms 173 ms
OverFeat:conv5 1832 ms 466 ms 524 ms 315 ms

三:NNPACK支持的层
  • 卷积层 (Convolutional layer
  • 全连接层 (Fully-connected layer
  • 池化层 (Max pooling layer
  • ReLU layer
  • Softmax layer

四:NNPACK 编译 (Linux OS)
1、编译安装 PeachPy
[cpp]  view plain  copy
  1. git clone https://github.com/Maratyszcza/PeachPy.git  
  2. cd PeachPy  
  3. [sudo] pip install --upgrade -r requirements.txt  
  4. python setup.py generate  
  5. [sudo] pip install --upgrade .  

2、安装ninja 和 ninja-syntax python 模块
[cpp]  view plain  copy
  1. sudo apt-get install ninja-build || brew install ninja  
  2. [sudo] pip install ninja-syntax  

3、下载编译NNPACK
[cpp]  view plain  copy
  1. git clone --recursive https://github.com/Maratyszcza/NNPACK.git  
  2. cd NNPACK  
  3. python ./configure.py  
  4. ninja  
注意:
编译nnpack过程如果出现一些找不到头文件等情况,一般是需要下载第三方库。在nnpack的包中有对于的目录third-party,分别下载,放到对应得目录中,并分别编译。

四:测试
NNPACK编译完成之后,在NNPACK-master/bin目录下有测试卷积、全连接等可执行程序。
例如,测试卷积输入通道 16 ,输出通道 16 , 输入图像180*180,kernel 3*3 ,迭代100次,


执行结果:


五、使用NNPACK 实现卷积
  • input channels: 1
  • output channels:1
  • input size:4*4
  • kernel size:3*3


1、 代码(conv_nnpack.c)

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<stdlib.h>  
  4. #include<unistd.h>  
  5. #include<sys/time.h>  
  6. #include<nnpack.h>  
  7. int main(int argc , char** argv)  
  8. {  
  9.     //init nnpack  
  10.     enum nnp_status init_status = nnp_initialize();  
  11.     if (init_status != nnp_status_success) {  
  12.         fprintf(stderr, "NNPACK initialization failed: error code %d\n", init_status);  
  13.         exit(EXIT_FAILURE);  
  14.     }  
  15.   
  16.         enum nnp_convolution_algorithm algorithm = nnp_convolution_algorithm_auto;  
  17.         const size_t batch_size = 1;  
  18.         const size_t input_channels = 1;  
  19.         const size_t output_channels = 1;  
  20.         const struct nnp_padding input_padding = { 0, 0, 0, 0 };  
  21.         const struct nnp_size input_size ={ 4, 4 };  
  22.         const struct nnp_size kernel_size = { 3, 3 },;  
  23.         const struct nnp_size output_size = {  
  24.                 .width = (input_padding.left + input_size.width + input_padding.right - kernel_size.width) / output_subsampling.width + 1,  
  25.                 .height = (input_padding.top + input_size.height + input_padding.bottom - kernel_size.height) / output_subsampling.height + 1  
  26.         };  
  27.     int iter=1;  
  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=NULL;  
  36.     //flase:only one thread, true: mutiple threads   
  37.     if (false) {   
  38.                 threadpool = pthreadpool_create(options.threads);  
  39.                 printf("Threads: %zu\n", pthreadpool_get_threads_count(threadpool));  
  40.     }  
  41.   
  42.     struct nnp_profile computation_profile;//use for compute time;  
  43.     //init input data  
  44.     int i,j;  
  45.     for(int c=0; c<input_channels;c++ ){  
  46.         for(i=0; i<input_size.height; i++){  
  47.             for(j=0; j<input_size.width; j++){  
  48.                 input[c*input_size.height*input_size.width+i*input_size.width+j] = (i*input_size.width+j)*1.0;  
  49.             }  
  50.         }  
  51.     }  
  52.   
  53.     //init kernel data  
  54.     for(int i=0; i<output_channels;i++ ){  
  55.         for(j=0; j<input_channels*kernel_size.height*kernel_size.width; j++){  
  56.             kernel[i*input_channels*kernel_size.height*kernel_size.width+j] = 1.0;            
  57.         }  
  58.     }  
  59.   
  60.     //init bias data  
  61.     for(int i=0; i<output_channels;i++ ){  
  62.         bias[i] = 1.0;  
  63.     }  
  64.   
  65.     //execute conv  
  66.     struct timeval conv_start;  
  67.     struct timeval conv_end;  
  68.     gettimeofday(&conv_start,NULL);  
  69.     for(int i=0;i<iter;i++){  
  70.         nnp_convolution_output(algorithm,  
  71.                     batch_size,  
  72.                     input_channels,  
  73.                     output_channels,  
  74.                     input_size,  
  75.                     input_padding,  
  76.                     kernel_size,  
  77.                     input,  
  78.                     kernel,  
  79.                     bias,  
  80.                     output,  
  81.                     threadpool,  
  82.                     &computation_profile);  
  83.     }  
  84.     gettimeofday(&conv_end,NULL);  
  85.     //printf ouput data  
  86.     for(i=0;i<output_channels; i++){  
  87.         for(j=0;j<output_size.height*output_size.width; j++){  
  88.             printf("%f\t",output[i*output_size.height*output_size.width+j]);      
  89.         }  
  90.         printf("\n");     
  91.     }  
  92.     float conv_time_use = 1000.0*(float)(conv_end.tv_sec-conv_start.tv_sec)+(float)(conv_end.tv_usec-conv_start.tv_usec)/1000.0;  
  93.     printf("conv Time use = %f(ms)\n",conv_time_use);  
  94.     printf("conv mean Time use = %f(ms) / iter\n",conv_time_use/iter);  
  95.     return 0;  
  96. }  

2、编译


编译,要链接 -lnnpack -lphterad 。-lphterad是第三方库pthreadpool使用pthread创建线程,pthreadpool是根据平台CPU的核数,创建对应数量的线程。此处代码false使用一个线程。

3、输出结果:


六:NNPACK与 im2col+sgemm卷积性能对比
  • im2col+sgemm使用openblas
  • intput channels : 16
  • output channels :16
  • input size : 360*360
  • kernel size: 2*2 , 3*3, 5*5
如下图:

图 nnpack vs im2col_segemm

  2 3 5 10
nnpack 6.69ms 7.38ms 9.71ms 26.44ms
im2col_sgemm 37.83ms 86.95ms 236.91ms 929.66ms
表 nnpack vs im2col_segemm
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值