【问题标题】:Code to improve with neon使用霓虹灯改进的代码
【发布时间】:2012-02-21 17:06:46
【问题描述】:

我试图改进一些代码,但我无法做到,所以我在这里寻求帮助,我也尝试过使用内在函数,但是如果你想使用内在函数,你需要使用 GCC 编译器,这个编译器编译速度较慢的代码比 LLVM,那么所有的代码都会变慢,所以最好的选择是直接使用 asm。 我把我想改进的两个功能,还有霓虹灯中的代码,代码返回的是无意义的数字。 我真的需要这方面的帮助,任何指向正确方向的点都可以帮助我很多。

我要改进的代码:

inline unsigned des(const unsigned char* v0)
{
unsigned r;
r = v0[0]*v0[0];
r += v0[1]*v0[1];
r += v0[2]*v0[2]; 
r += v0[3]*v0[3];
r += v0[4]*v0[4];
r += v0[5]*v0[5]; 
r += v0[6]*v0[6];
r += v0[7]*v0[7];
return r;
}


inline unsigned  suma(const unsigned char* v0)
{
unsigned r;
r = v0[0];
r += v0[1];
r += v0[2]; 
r += v0[3];
r += v0[4];
r += v0[5]; 
r += v0[6];
r += v0[7];
return r;
}

霓虹灯代码不起作用

unsigned desneon(unsigned v0[8])
{
asm volatile (
              "vld1.32      {d2- d5}, [%0]          \n\t"   
              "vld1.32      {d6- d9}, [%0]          \n\t"   
              "vmul.s32         d0, d2, d6              \n\t"   //d0= d2*d6
              "vmla.s32         d0, d3, d7              \n\t"   //d0 = d0 + d3*d7 
               "vmla.s32        d0, d4, d8              \n\t"   //d0 = d0 + d4*d8 
                "vmla.s32       d0, d5, d9              \n\t"   //d0 = d0 + d5*d9 
             "vpadd.s32         d0, d0                  \n\t"   //d0 = d[0] + d[1]


              :: "r"(v0) : 
              );    
}

非常感谢!!!

【问题讨论】:

  • 您实际上并没有从该方法返回任何内容。 d0 最终会得到您想要的结果,我很确定,但您实际上需要返回它。
  • 为什么不在 Accelerate.framework 中使用 vDSP 函数?
  • vDSP 正在使用浮点数,我想这会使应用程序变慢,不是吗?

标签: c ios assembly arm neon


【解决方案1】:

您需要实际返回该值。我想你想要这样的东西:

unsigned desneon(unsigned v0[8])
{
    unsigned outlo;
    __asm__ volatile (
                      "vld1.32      {d2- d5}, [%1]          \n\t"   
                      "vld1.32      {d6- d9}, [%1]          \n\t"   
                      "vmul.s32     d0, d2, d6              \n\t"   //d0= d2*d6
                      "vmla.s32     d0, d3, d7              \n\t"   //d0 = d0 + d3*d7 
                      "vmla.s32     d0, d4, d8              \n\t"   //d0 = d0 + d4*d8 
                      "vmla.s32     d0, d5, d9              \n\t"   //d0 = d0 + d5*d9
                      "vpadd.s32    d0, d0                  \n\t"   //d0 = d[0] + d[1]
                      "vmov         %0, r4, d0              \n\t"
                      :"=r"(outlo)
                      :"r"(v0)
                      :"d0", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "r4"
                      );
    return outlo;
}

我检查了一下,它似乎给了我正确的结果。正如@Nyx0uf 所说,您可能想看看 Accelerate 框架 - 它有很多有用的东西可以通过标准方法调用而不是手写 NEON 来实现。

【讨论】:

  • 感谢它的工作!加速框架存在问题,在我看来,这个框架似乎总是使用浮点数,使用浮点数会使应用程序变慢。
  • 即使有一些改进也有点慢,我把改进的代码放在上面,但是非常感谢我有一个可以改进它的工作示例:D。
【解决方案2】:
  • 为什么在数据未签名时进行签名操作?
  • 为什么要读取相同的数据两次?
  • 你的 C 代码的输入数据是 8 位的,但霓虹灯的代码是 32 位的。

假设输入数据为 32 位,我建议:

unsigned desneon(unsigned v0[8])
{
asm volatile (
             "vldmia      {q0-q1}, [%0]          \n\t"   
             "vmul.u32    q0, q0, q0             \n\t"
             "vmla.u32    q0, q1, q1             \n\t"
             "vpaddl.u32  q0, q0                 \n\t"    
             "vadd.u64    d0, d0, d1             \n\t"    
             "vmov        r0, s0                 \n\t"    

              :: "r"(v0) : 
              );    
}

虽然看起来非常短并且似乎已经过优化,但这个霓虹灯版本不会更快(甚至更慢),因为:

  • 管道几乎每一步都互锁
  • 在“vmov r0,s0”(11 个周期)之前出现了巨大的问题

在这种情况下,我建议您坚持使用原始 C 代码。

【讨论】:

  • 嗨,杰克,感谢您的回答,我需要更改这一行“”vldmia %0 , {q0-q1} \n\t“”,当我运行它时,看起来正在做恶意的东西,应用程序只是停止并且什么都不做,没有错误,没有杀死,没有内存......什么都没有,也许它与程序计数器有关,但我没有找到问题。
  • 可能是因为最后一行 vmov。我对内联汇编不是很熟悉。只需更改它,以便返回 s0 的值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 2016-04-02
相关资源
最近更新 更多