2012-12-14 16 views
7

Sto vettorializzando un loop interno con ARM NEON intrinsec (llvm, iOS). Generalmente utilizzo float32x4_t s. Il mio calcolo termina con la necessità di sommare tre dei quattro float in questo vettore.Sommando 3 corsie in un NEON float32x4_t

A questo punto posso tornare ai float C e vst1q_f32 per ottenere i quattro valori e sommare i tre che mi servono. Ma immagino che potrebbe essere più efficace se c'è un modo per farlo direttamente con il vettore in un'istruzione o due, e quindi solo prendere un risultato a corsia singola, ma non sono riuscito a capire un percorso chiaro per farlo.

Sono nuovo alla programmazione NEON e la "documentazione" esistente è piuttosto orribile. Qualche idea? Grazie!

risposta

2

Sembra che tu voglia utilizzare (qualche versione di) VLD1 per caricare zero nella tua corsia extra (a meno che tu non possa fare in modo che sia già zero), seguito da due istruzioni VPADDL per sommare a coppie quattro corsie in due e poi due corsie in una.

3

Puoi azzerare il quarto elemento? Forse solo copiandolo e usando vset_lane_f32?

Se è così, è possibile utilizzare le risposte da Sum all elements in a quadword vector in ARM assembly with NEON come:

float32x2_t r = vadd_f32(vget_high_f32(input), vget_low_f32(input)); 
return vget_lane_f32(vpadd_f32(r, r), 0); // vpadd adds adjacent elements 

Anche se questo in realtà fa un po 'più lavoro di quanto è necessario, quindi potrebbe essere più veloce solo estrarre i tre carri con vget_lane_f32 e aggiungere loro.

4

Dovresti essere in grado di utilizzare l'unità VFP per tale compito. NEON e VFP condividono la stessa banca di registro, il che significa che non è necessario mescolare i registri per ottenere il vantaggio di una unità e possono anche avere viste differenti degli stessi bit di registro.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204j/ch05s03s02.html

tuo float32x4_t è a 128 bit, quindi deve sedere su un Quad (Q) registrarsi. Se si utilizza esclusivamente arm intrinsec non si sa quale si sta utilizzando. Problema c'è se è seduto sopra il 4, VFP non può vederlo come una singola precisione (per il lettore curioso: ho mantenuto questo semplice poiché ci sono differenze tra le versioni VFP e questo è il requisito minimo nullo). Quindi sarebbe meglio spostare il tuo float32x4_t in un registro fisso come Q0. Dopodiché puoi sommare registri come S0, S1, S2 con vadd.f32 e spostare il risultato su un registro ARM.

Alcune avvertenze ... VFP e NEON sono teoricamente diverse unità di esecuzione che condividono lo stesso banco di registri e pipeline. Non sono sicuro che questo approccio sia migliore di altri, non ho bisogno di dire ma, ancora una volta, dovresti fare un benchmark. Anche questo approccio non è ottimizzato con il neon intrinseco, quindi probabilmente avresti bisogno di creare il tuo codice con l'assembly inline.

ho fatto un semplice frammento di vedere come questo può essere simile e mi è venuta in mente questo:

#include "arm_neon.h" 

float32_t sum3() {   
     register float32x4_t v asm ("q0"); 
     float32_t ret; 

     asm volatile(
     "vadd.f32  s0, s1\n" 
     "vadd.f32  s0, s2\n" 
     "vmov   %[ret], s0\n" 
     : [ret] "=r" (ret) 
     : 
     :); 

     return ret; 
} 

objdump di esso assomiglia (compilato con gcc -O3 -mfpu = neon -mfloat- abi = softfp)

00000000 <sum3>: 
    0: ee30 0a20 vadd.f32 s0, s0, s1 
    4: ee30 0a01 vadd.f32 s0, s0, s2 
    8: ee10 3a10 vmov r0, s0 
    c: 4770  bx lr 
    e: bf00  nop 

mi piacerebbe davvero sentire le vostre impressioni se si dà a questo un andare!

Problemi correlati