Extensión del vector GCC C: ¿Cómo verificar si el resultado de CUALQUIER comparación de elementos es verdadero, y cuál?
⏰ 5 minutos de lectura
usuario1649948
Soy nuevo en las extensiones de vector C de GCC. Según el manual, el resultado de comparar un vector con otro en la forma (test = vec1 > vec2;) es que “test” contiene un 0 en cada elemento que es falso y un -1 en cada elemento que es verdadero.
Pero, ¿cómo verificar rápidamente si CUALQUIERA de las comparaciones de elementos fue verdadera? Y, además, ¿cómo saber cuál es el primer elemento para el que la comparación fue verdadera?
Quiero determinar si la “prueba” contiene alguna verdad (elementos distintos de cero). En este caso, quiero que “prueba” se reduzca a verdadero, porque existe un elemento para el cual vec1 es mayor que vec2 y, por lo tanto, un elemento en prueba que contiene -1.
Además, o alternativamente, quiero descubrir rápidamente QUÉ elemento no pasa la prueba. En este caso, este sería simplemente el número 2. Dicho de otra manera, quiero probar cuál es el primer elemento distinto de cero.
int hasAnyTruth = ...; // should be non-zero. "bool" works too since C99
int whichTrue = ...; // should contain 2, because test[2] == -1
Me imagino que podríamos usar un comando simd de reducción y suma (?) para sumar todo en el vector en un número y comparar esa suma con 0, pero no sé cómo (o si hay una forma más rápida). Supongo que se necesita alguna forma de argmax para la segunda pregunta, pero nuevamente, no sé cómo indicarle a GCC que lo use en los vectores.
_mm_movemask_epi8()
– Místico
23 de julio de 2015 a las 20:49
Vaya, me gusta esto. 1) ¿Es portátil? 2) ¿Alguna ventaja sobre memcmp? 3) ¿Funciona con registros de 256 bits (AVX) o vectores con diferente número de elementos?
– usuario1649948
23 de julio de 2015 a las 20:56
Es más portátil que las extensiones vectoriales GCC. Está estandarizado por Intel, por lo que funcionará en todos los principales compiladores: GCC, Clang, MSVC, ICC, etc… software.intel.com/sites/landingpage/IntrinsicsGuide
– Místico
23 de julio de 2015 a las 20:59
Hay una instrucción para eso en x86: ptest.
– FEO
23 de julio de 2015 a las 21:22
Sospecho que la forma más rápida de implementar memcmp() en un x86 con (al menos) sse4_1 usará ptest. Si desea usarlo en gcc, está disponible en microarquitecturas x86 que lo admiten como __builtin_ia32_ptestc128/ptestnzc128/ptestz128/256.
– FEO
23 de julio de 2015 a las 21:36
La extensión del vector de Clang hace un buen trabajo con el any función.
los any función Yo diría que es una función vectorial crítica, por lo que los compiladores deberían proporcionar una función integrada como lo hacen para la reproducción aleatoria (por ejemplo, __builtin_shuffle para CCG y __builtin_shufflevector para clang) o el compilador debe ser lo suficientemente inteligente como para descubrir el código óptimo como lo hace Clang al menos para SSE y AVX pero no para AVX512.
+1 Me quedé sin votos positivos cuando respondiste por primera vez, ¡pero buena respuesta! Perdón por el que publiqué en la comunidad antes de copiar la respuesta de Mysticial de los comentarios. Eso fue en un momento en que me dediqué a tratar de moderar y preservar la “posteridad del sitio”. Lo eliminaría, excepto que no puedo hasta que se cambie la respuesta.
– usuario4842163
22 de enero de 2018 a las 19:18
De Mística:
_mm_movemask_epi8()
Es más portátil que las extensiones vectoriales GCC. Está estandarizado por Intel, por lo que funcionará en todos los principales compiladores: GCC, Clang, MSVC, ICC, etc…
Esto no es más portátil que las extensiones vectoriales de GCC. Por ejemplo, es inútil en ARM.
– bosón Z
17 de enero de 2018 a las 14:29
@Zboson Tengo que referirme a Mysticial para obtener una respuesta, ya que terminé simplemente publicando en la comunidad su comentario de la pregunta como una respuesta para la posteridad, ya que la pregunta originalmente no tuvo respuestas durante un buen tiempo y parecía resuelta a través de comentarios, definitivamente no hardware. -portátil.
Para hacer esto, podemos usar funciones intrínsecas, al usar funciones intrínsecas podemos lograr más velocidad en la ejecución del código. Consulte el siguiente enlace
¿Ha sido útil esta solución?
Tu feedback nos ayuda a saber si la solución es correcta y está funcionando. De esta manera podemos revisar y corregir el contenido.
Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos.
Configurar y más información
_mm_movemask_epi8()
– Místico
23 de julio de 2015 a las 20:49
Vaya, me gusta esto. 1) ¿Es portátil? 2) ¿Alguna ventaja sobre memcmp? 3) ¿Funciona con registros de 256 bits (AVX) o vectores con diferente número de elementos?
– usuario1649948
23 de julio de 2015 a las 20:56
Es más portátil que las extensiones vectoriales GCC. Está estandarizado por Intel, por lo que funcionará en todos los principales compiladores: GCC, Clang, MSVC, ICC, etc… software.intel.com/sites/landingpage/IntrinsicsGuide
– Místico
23 de julio de 2015 a las 20:59
Hay una instrucción para eso en x86:
ptest
.– FEO
23 de julio de 2015 a las 21:22
Sospecho que la forma más rápida de implementar
memcmp()
en un x86 con (al menos) sse4_1 usaráptest
. Si desea usarlo en gcc, está disponible en microarquitecturas x86 que lo admiten como__builtin_ia32_ptestc128/ptestnzc128/ptestz128/256
.– FEO
23 de julio de 2015 a las 21:36