Npu 执行runGraph 性能问题

项目是跑openpose的(android 平台)。 我用的google的posenet. 基于tensorflowlite
目前已经跑通。测试发现性能很差。
用npu之前我用的tensorflowlite-api: vim3 上测试耗时不到300ms.
但是用了npu 之后耗时470ms左右. 而且470是执行vnn_ProcessGraph花的时间…

vim_npu: Start run graph [1] times...
vim_npu: Run the 1 time: 464.00ms or 464475.00us
vim_npu: vxProcessGraph execution time:
vim_npu: Total   464.00ms or 464593.00us
vim_npu: Average 464.59ms or 464593.00us

下面是转化case代码后的ProcessGraph 关键代码。求教怎么回事?

static vsi_status vnn_ProcessGraph
       (
               vsi_nn_graph_t *graph
       )
{
   vsi_status status = VSI_FAILURE;
   int32_t i,loop;
   char *loop_s;
   uint64_t tmsStart, tmsEnd, sigStart, sigEnd;
   float msVal, usVal;

   status = VSI_FAILURE;
   loop = 1; /* default loop time is 1 */
   loop_s = getenv("VNN_LOOP_TIME");
   if(loop_s)
   {
       loop = atoi(loop_s);
   }

   /* Run graph */
   tmsStart = get_perf_count();
   printf("Start run graph [%d] times...\n", loop);
   for(i = 0; i < loop; i++)
   {
       sigStart = get_perf_count();
       status = vsi_nn_RunGraph( graph );
       if(status != VSI_SUCCESS)
       {
           printf("Run graph the %d time fail\n", i);
       }
       TEST_CHECK_STATUS( status, final );

       sigEnd = get_perf_count();
       msVal = (sigEnd - sigStart)/1000000;
       usVal = (sigEnd - sigStart)/1000;
       printf("Run the %u time: %.2fms or %.2fus\n", (i + 1), msVal, usVal);
   }
   tmsEnd = get_perf_count();
   msVal = (tmsEnd - tmsStart)/1000000;
   usVal = (tmsEnd - tmsStart)/1000;
   printf("vxProcessGraph execution time:\n");
   printf("Total   %.2fms or %.2fus\n", msVal, usVal);
   printf("Average %.2fms or %.2fus\n", ((float)usVal)/1000/loop, ((float)usVal)/loop);

   final:
   return status;
}

@Frank @jasonl

@heaven7

  1. 首先板子上的NPU是处理int数据的,跟使用GPU或者使用CPU时,可以处理浮点数据是不一样的.这就设计到了模型里面的浮点运算部分如何转化的问题.这就是这个转换工具的主要作用,
  2. 将模型转换成可以在NPU上面的运算的算子.这就不可避免要使用到近似运算,将浮点的运算转换成int.
  3. 这里就有精度损失和效率降低两个相互矛盾的问题. 工具本身是对这两部分做了平衡的.但是由于工具本身不开源,所以内部实现方法我们不得而知.
  4. 你这种情况大都是某一个或者某一些网络层的浮点运算在转换后变得冗杂,效率降低太多. 这个工具对某些特定算子的支持不是很好.
  5. 建议你可以在文档里面查查,'Neural Network Layer and Operation Support Guide (02)(ref.v1.17-20200623).pdf,看看你的模型里面是不是所有层都有很好的支持.
  6. 解决方法是修改原本的神经网络模型,在转换之前就对浮点运算的算子做近似处理.然后重新训练.再尝试再转换,再重新优化.

好的,谢谢. ffffffffffffffff

我今天通过重新转化case代码, 性能现在好了process graph 10ms左右,新问题又出现了:
同一张图片的结果的差异比较大。

转化模型差异:
之前–channel-mean-value之前用的(128,128,128,1)现在用的(128,128,128,128)

结果差异:(这个是同一张图片,使用tflite-api和 npu的输出差异)

还有一点,我发现case代码中输出的shape 是倒过来的。比如
“output_59”: {
“name”: “output”,
“shape”: [
1,
9,
9,
17
],
“format”: “nhwc”,
“dtype”: “asymmetric_affine”,
“quantize”: {
“qtype”: “u8”,
“zero_point”: [
177
],
“scale”: [
0.09003465622663498
]
}
},
case代码调用:

//这里的shape 相反?? why?
 attr.size[0] = 17;
    attr.size[1] = 9;
    attr.size[2] = 9;
    attr.size[3] = 1;
    attr.dim_num = 4;
    attr.dtype.scale = 0.090034656;
    attr.dtype.zero_point = 177;
    attr.dtype.qnt_type = VSI_NN_QNT_TYPE_AFFINE_ASYMMETRIC;
    NEW_NORM_TENSOR(norm_tensor[1], attr, VSI_NN_TYPE_UINT8);

为什么会这样呢?
@Frank

@heaven7 输出的shape是反的,你后处理就反过来处理,工具本身不开源,这种我也不清楚内部是怎么运转的 .你设置成128 128 128 1 ,是不对的,这样子怎么做归一处理.这样子就值处理了均值,没有做归一处理了.tflite-api我这边没有使用过,安卓部分不是由我负责的.

请教下vsi_nn_RunGraph()耗时比较长,最终有优化没,如何优化的