用霓虹灯改进的代码

时间:2012-02-21 17:06:47

标签: c ios assembly arm neon

我试图改进一些代码,但我不能,所以我在这里寻求帮助,我也试过内在函数,但是如果你想使用内在的你需要使用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) : 
              );    
}

非常感谢!!!

2 个答案:

答案 0 :(得分:2)

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

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。

答案 1 :(得分:0)

  • 为什么在数据未签名时签名操作?
  • 为什么要两次读取相同的数据?
  • 您的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代码。