Sto cercando di creare un decodificatore veloce per BPSK
utilizzando gli intrinseci AVX
di Intel. Ho una serie di numeri complessi che sono rappresentati come galleggianti intercalati, ma a causa della modulazione BPSK
sono necessari solo la parte reale (o i float indicizzati pari). Ogni floatviene mappato su 0
, quando x < 0
e su 1
se x >= 0
. Questa operazione viene eseguita utilizzando la seguente procedura:Confronto con NaN utilizzando AVX
static inline void
normalize_bpsk_constellation_points(int32_t *out, const complex_t *in, size_t num)
{
static const __m256 _min_mask = _mm256_set1_ps(-1.0);
static const __m256 _max_mask = _mm256_set1_ps(1.0);
static const __m256 _mul_mask = _mm256_set1_ps(0.5);
__m256 res;
__m256i int_res;
size_t i;
gr_complex temp;
float real;
for(i = 0; i < num; i += COMPLEX_PER_AVX_REG){
res = _mm256_load_ps((float *)&in[i]);
/* clamp them to avoid segmentation faults due to indexing */
res = _mm256_max_ps(_min_mask, _mm256_min_ps(_max_mask, res));
/* Scale accordingly for proper indexing -1->0, 1->1 */
res = _mm256_add_ps(res, _max_mask);
res = _mm256_mul_ps(res, _mul_mask);
/* And then round to the nearest integer */
res = _mm256_round_ps(res, _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC);
int_res = _mm256_cvtps_epi32(res);
_mm256_store_si256((__m256i *) &out[2*i], int_res);
}
}
primo luogo, morsetto tutti i galleggianti ricevuti nell'intervallo [-1, 1]
. Quindi, dopo un corretto ridimensionamento, il risultato viene arrotondato al numero intero più vicino. Questo mapperà tutti i galleggianti sopra 0.5
a 1
e tutti galleggiano sotto 0.5
a 0
.
La procedura funziona correttamente se i valori di inserimento sono normali. Tuttavia, a causa di alcune situazioni nelle fasi precedenti, esiste la possibilità che alcuni valori di inserimento siano NaN
o -NaN
. In questo caso, i numeri "NaN" vengono propagati attraverso lo _mm256_max_ps()
, _mm256_min_ps()
e tutte le altre funzioni AVX
risultanti in un mapping intero di -2147483648
che, naturalmente, causa il blocco del mio programma a causa di indicizzazione non valida.
Esiste una soluzione alternativa per evitare questo problema o almeno impostare NaN
su 0
utilizzando AVX
?
'(float *) e in [i]' 'getta una complessa *' a 'float *'. Invito a comportamento indefinito. – Olaf
No, 'complex_t' punta a un'area di memoria con float interlacciati che rappresentano un numero complesso. – Manos
Ancora un problema di aliasing imo. E il layout di complex_t è definito dall'implementazione. – Olaf