Код для улучшения с неоном - PullRequest
1 голос
/ 21 февраля 2012

Я пытался улучшить некоторый код, но я не смог, поэтому я прошу помощи здесь, я также попытался с внутренними, но если вы хотите использовать встроенные, вам нужно использовать компилятор 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 ]

2 голосов
/ 21 февраля 2012

Вы должны на самом деле вернуть значение. Я думаю, что вы хотите что-то вроде этого:

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 вручную.

0 голосов
/ 19 марта 2012
  • зачем подписывать операции, когда данные не подписаны?
  • зачем читать одни и те же данные дважды?
  • входные данные вашего кода 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.

...