2012-05-15 14 views
6

Come posso prendere il reciproco (inverso) dei float con le istruzioni SSE, ma solo per valori non pari a zero?SSE: reciproco se non zero

Sfondo sotto:

voglio di normalizzare una serie di vettori in modo che ogni dimensione ha la stessa media. In C questo può essere codificato come:

float vectors[num * dim]; // input data 

// step 1. compute the sum on each dimension 
float norm[dim]; 
memset(norm, 0, dim * sizeof(float)); 
for(int i = 0; i < num; i++) for(int j = 0; j < dims; j++) 
    norm[j] += vectors[i * dims + j]; 
// step 2. convert sums to reciprocal of average 
for(int j = 0; j < dims; j++) if(norm[j]) norm[j] = float(num)/norm[j]; 
// step 3. normalize the data 
for(int i = 0; i < num; i++) for(int j = 0; j < dims; j++) 
    vectors[i * dims + j] *= norm[j]; 

Ora, per motivi di prestazioni, voglio farlo usando intinsics SSE. Setp 1 e step 3 sono facili, ma sono bloccato al punto 2. Non riesco a trovare alcun esempio di codice o istruzioni SSE ovvie per prendere il recirpocal di un valore se non è zero. Per la divisione, _mm_rcp_ps esegue il trucco e forse lo combina con una mossa condizionale, ma come ottenere una maschera che indica quale componente è zero?

Non ho bisogno il codice per l'algoritmo descritto in precedenza, solo il "inversa se non zero" funzione:

__m128 rcp_nz_ps(__m128 input) { 
    // ???? 
} 

Grazie!

risposta

11
__m128 rcp_nz_ps(__m128 input) { 
    __m128 mask = _mm_cmpeq_ps(_mm_set1_ps(0.0), input); 
    __m128 recip = _mm_rcp_ps(input); 
    return _mm_andnot_ps(mask, recip); 
} 

Ciascuna corsia mask sia impostato b111...11 se l'ingresso è zero, e b000...00 altrimenti. E-non con quella maschera sostituisce elementi del reciproco corrispondenti a zero input con zero.

+1

Dannazione, è stato veloce. Stavo lavorando da solo e tu mi hai battuto. +1 – Mysticial

+0

Grazie. C'è un modo per "testare" invece di "confrontare" ed evitare di usare un registro impostato su null? Mi stavo solo chiedendo ... – Antoine

+0

Oltre all'ultima riga, c'è un refuso: l'input dovrebbe essere destinatario. – Antoine