Obtener miembro de m128 por índice?
Tengo un código, originalmente dado a mí por alguien que trabaja con MSVC, y estoy tratando de que funcione en Clang. Esta es la función con la que estoy teniendo problemas:
float vectorGetByIndex( __m128 V, unsigned int i )
{
assert( i <= 3 );
return V.m128_f32[i];
}
El error que obtengo es el siguiente:
Member reference has base type '__m128' is not a structure or union.
He mirado alrededor y he encontrado que Clang (y tal vez GCC) tiene un problema con el tratamiento de __m128 como una estructura o unión. Sin embargo, no he logrado encontrar una respuesta directa sobre cómo puedo recuperar estos valores. He intentado usar el operador de subíndice y no pude haz eso, y he echado un vistazo a la enorme lista de funciones intrínsecas de SSE y aún no he encontrado una apropiada.
4 answers
Una unión es probablemente la forma más portátil de hacer esto:
union {
__m128 v; // SSE 4 x float vector
float a[4]; // scalar array of 4 floats
} U;
float vectorGetByIndex(__m128 V, unsigned int i)
{
U u;
assert(i <= 3);
u.v = V;
return u.a[i];
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-27 15:16:17
Incluso si SSE4.1 está disponible y i
es una constante de tiempo de compilación, no puede usar pextract
etc. de esta manera:
// broken code starts here
template<unsigned i>
float vectorGetByIndex( __m128 V) {
return _mm_extract_epi32(V, i);
}
// broken code ends here
No lo elimino porque es un recordatorio útil de cómo no hacer las cosas y dejar que se presente como una humillación pública.
Mejor uso
template<unsigned i>
float vectorGetByIndex( __m128 V) {
union {
__m128 v;
float a[4];
} converter;
converter.v = V;
return converter.a[i];
}
Que funcionará independientemente del conjunto de instrucciones disponible.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-29 11:53:13
Como una modificación a la solución de hirschhornsalz, si i
es una constante en tiempo de compilación, podría evitar la ruta de unión por completo usando un shuffle / store:
template<unsigned i>
float vectorGetByIndex( __m128 V)
{
#ifdef __SSE4_1__
return _mm_extract_epi32(V, i);
#else
float ret;
// shuffle V so that the element that you want is moved to the least-
// significant element of the vector (V[0])
V = _mm_shuffle_ps(V, V, _MM_SHUFFLE(i, i, i, i));
// return the value in V[0]
return _mm_cvtss_f32(V);
#endif
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-22 21:56:30
La forma en que uso es
union vec { __m128 sse, float f[4] };
float accessmember(__m128 v, int index)
{
vec v.sse = v;
return v.f[index];
}
Parece funcionar bastante bien para mí.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-10 04:16:33