2012-05-15 9 views
6

Wie kann ich die reziproke (inverse) von Floats mit SSE-Anweisungen, aber nur für nicht Null Werte nehmen?SSE: reziprok wenn nicht null

Hintergrund unten:

Ich möchte ein Array von Vektoren normalisieren, so daß jede Dimension die gleiche durchschnittliche aufweist. In C kann diese codiert werden als:

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]; 

nun aus Leistungsgründen, ich möchte, dies zu tun SSE intinsics verwenden. Setp 1 und Step 3 sind einfach, aber ich stecke bei Schritt 2 fest. Ich finde anscheinend keine Code-Probe oder offensichtlichen SSE-Befehl, um das Rezirkular eines Wertes zu nehmen, wenn nicht Null ist. Für die Division macht _mm_rcp_ps den Trick und kombiniert es vielleicht mit einer bedingten Bewegung, aber wie erhält man eine Maske, die anzeigt, welche Komponente Null ist?

Ich brauche den Code nicht zu dem oben beschriebenen Algorithmus, sondern nur die „inverse wenn nicht Null“ Funktion:

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

Dank! sonst

Antwort

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); 
} 

Jede Spur von mask ist entweder b111...11, wenn der Eingang Null und b000...00 ist. Und - nicht mit dieser Maske ersetzt Elemente des Kehrwertes entsprechend einer Nulleingabe mit Null.

+1

Verdammt, das war schnell. Ich habe alleine gearbeitet und du hast mich dazu geschlagen. +1 – Mysticial

+0

Danke. Gibt es eine Möglichkeit, "zu testen" anstatt "zu vergleichen", und zu vermeiden, einen Registersatz auf Null zu setzen? Ich frage mich nur ... – Antoine

+0

Neben der letzten Zeile gibt es einen Tippfehler: Eingabe sollte recip sein. – Antoine

Verwandte Themen