2012-01-26 6 views
0

Я хочу, чтобы преобразовать следующую функцию в NEON:преобразования краткосрочной Int и суммируют с NEON

int dot4_c(unsigned char v0[4], unsigned char v1[4]){ 
     int r=0; 
     r = v0[0]*v1[0]; 
     r += v0[1]*v1[1]; 
     r += v0[2]*v1[2]; 
     r += v0[3]*v1[3]; 
return r; 
} 

Я думаю, что почти сделать это, но есть ошибка, потому что она не работает хорошо

int dot4_neon_hfp(unsigned char v0[4], unsigned char v1[4]) 
{ 

asm volatile (
       "vld1.16  {d2, d3}, [%0]   \n\t" //d2={x0,y0}, d3={z0, w0} 
       "vld1.16  {d4, d5}, [%1]   \n\t" //d4={x1,y1}, d5={z1, w1} 
       "vcvt.32.u16  d2, d2     \n\t" //conversion 
       "vcvt.32.u16  d3, d3     \n\t" 
       "vcvt.32.u16  d4, d4     \n\t" 
       "vcvt.32.u16  d5, d5     \n\t" 

       "vmul.32  d0, d2, d4    \n\t" //d0= d2*d4 
       "vmla.32  d0, d3, d5    \n\t" //d0 = d0 + d3*d5 
       "vpadd.32   d0, d0    \n\t" //d0 = d[0] + d[1] 
       :: "r"(v0), "r"(v1) : 
      );  

} 

Как я могу заставить это работать?

+0

Лучше использовать встроенные средства для этого в первом случае, а не в качестве исходного asm - намного проще заставить его работать, а производительность будет близка к возможному с помощью оптимизированного вручную asm. –

+1

Это не так просто для NEON манипулировать только 4 байтами. NEON используется для создания массового результата на большом количестве данных. Ваш код NEON не может работать, потому что нет способа загрузить только 4 байта с помощью NEON. Ваш VLD1.16 будет загружать 16 байтов каждый! – webshaker

ответ

2

Как уже упоминалось, вы должны загрузить не менее 8 байтов за раз с помощью NEON. Пока загрузка не проходит мимо конца вашего буфера, вы можете игнорировать дополнительные байты. Вот как сделать это с встроенными функциями:

uint8x8_t v0_vec, v1_vec; 
uint16x8_t vproduct; 
uint32x2_t vsum32; 

v0_vec = vld1_u8(v0); // extra bytes will be ignored as long as you can safely read them 
v1_vec = vld1_u8(v1); 
// you didn't specify if the product of your vector fits in 8-bits, so I assume it needs to be widened to 16-bits 
vproduct = vmull_u8(v0_vec, v1_vec); 
vsum32 = vpaddl_u16(vget_low_u16(vproduct)); // pairwise add lower half (first 4 u16's) 
return vsum32.val[0] + vsum32.val[1]; 

Если вы совсем не можете загрузить 8 байт из источника указателей, вы можете вручную загрузить 32-битное значение в регистр NEON (4 байта), а затем превратить его в собственный внутренний тип.