¿Qué significa la comparación ordenada / desordenada?


Mirando los operadores SSE

CMPORDPS - ordered compare packed singles
CMPUNORDPS - unordered compare packed singles

¿Qué significa ordenado y desordenado? Busqué instrucciones equivalentes en el conjunto de instrucciones x86, y solo parece haber desordenado (FUCOM).

Author: Bo Persson, 2011-12-25

4 answers

Una comparación ordenada comprueba si ninguno de los operando es NaN. Por el contrario, una comparación desordenada comprueba si cualquiera de los operando es un NaN.

Esta página da más información sobre esto: {[28]]}

La idea aquí es que las comparaciones con NaN son indeterminadas. (no puede decidir el resultado) Por lo que una comparación ordenada/desordenada comprueba si esto es (o no es) el caso.

double a = 0.;
double b = 0.;

__m128d x = _mm_set1_pd(a / b);     //  NaN
__m128d y = _mm_set1_pd(1.0);       //  1.0
__m128d z = _mm_set1_pd(1.0);       //  1.0

__m128d c0 = _mm_cmpord_pd(x,y);    //  NaN vs. 1.0
__m128d c1 = _mm_cmpunord_pd(x,y);  //  NaN vs. 1.0
__m128d c2 = _mm_cmpord_pd(y,z);    //  1.0 vs. 1.0
__m128d c3 = _mm_cmpunord_pd(y,z);  //  1.0 vs. 1.0
__m128d c4 = _mm_cmpord_pd(x,x);    //  NaN vs. NaN
__m128d c5 = _mm_cmpunord_pd(x,x);  //  NaN vs. NaN

cout << _mm_castpd_si128(c0).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c1).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c2).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c3).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c4).m128i_i64[0] << endl;
cout << _mm_castpd_si128(c5).m128i_i64[0] << endl;

Resultado:

0
-1
-1
0
0
-1
  • Comparación ordenada de NaN y 1.0 da false.
  • Comparación desordenada de NaN y 1.0 da true.
  • Ordenó comparación de 1.0 y 1.0 da true.
  • Desordenada comparación de 1.0 y 1.0 da false.
  • Comparación ordenada de NaN y Nan da false.
  • Comparación desordenada de NaN y NaN da true.
 25
Author: Mysticial,
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
2016-07-21 20:34:40

Intel guía: http://intel80386.com/simd/mmx2-doc.html contiene ejemplos de los dos que son bastante sencillo:

CMPORDPS Comparar Escalares Paralelos Ordenados

Opcode Ciclos de Instrucción 0F C2 .. 07 2 (3) CMPORDPS xmm reg, xmm reg/mem128

CMPORDPS op1, op2

Op1 contiene 4 valores de punto flotante de precisión única de 32 bits op2 contiene 4 valores de coma flotante de precisión única de 32 bits

op1[0] = (op1[0] != NaN) && (op2[0] != NaN)
op1[1] = (op1[1] != NaN) && (op2[1] != NaN)
op1[2] = (op1[2] != NaN) && (op2[2] != NaN)
op1[3] = (op1[3] != NaN) && (op2[3] != NaN)

TRUE  = 0xFFFFFFFF
FALSE = 0x00000000

CMPUNORDPS Compare Escalares Paralelos Desordenados

Opcode Ciclos de Instrucción 0F C2 .. 03 2 (3) CMPUNORDPS xmm reg, xmm reg/mem128

CMPUNORDPS op1, op2

Op1 contiene 4 valores de punto flotante de precisión única de 32 bits op2 contiene 4 valores de coma flotante de precisión única de 32 bits

op1[0] = (op1[0] == NaN) || (op2[0] == NaN)
op1[1] = (op1[1] == NaN) || (op2[1] == NaN)
op1[2] = (op1[2] == NaN) || (op2[2] == NaN)
op1[3] = (op1[3] == NaN) || (op2[3] == NaN)

TRUE  = 0xFFFFFFFF
FALSE = 0x00000000

La diferencia es Y (ordenado) vs O (desordenado).

 5
Author: AusCBloke,
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
2011-12-24 23:42:13

TL: DR : Unordered es una relación que dos valores FP pueden tener. El "Desordenado" en FUCOM significa que no genera una excepción FP cuando el resultado de la comparación no está ordenado, mientras que FCOM lo hace. Esto es lo mismo que la distinción entre OQ y OS cmpps predicados


ORD y UNORD son dos opciones de predicado para el cmppd / cmpps / cmpss / cmpsd insns (tablas completas en la entrada cmppd que es alfabéticamente primero). Ese extracto html tiene una tabla legible formateo, pero original PDF oficial de Intel es algo mejor. (Ver el wiki de etiquetas x86 para enlaces).

Dos operandos de coma flotante se ordenan entre sí si ninguno es NaN. Están desordenados si cualquiera es NaN. es decir, ordered = (x>y) | (x==y) | (x<y);. Así es, con coma flotante es posible que ninguna de esas cosas sea verdad. Para más locura de Punto flotante, ver La excelente serie de artículos de Bruce Dawson.

cmpps toma un predicado y produce un vector de resultados, en lugar de hacer una comparación entre dos escalares y establecer banderas para que pueda verificar cualquier predicado que desee después del hecho. Por lo tanto, necesita predicados específicos para todo lo que pueda verificar.


El equivalente escalar es comiss / ucomiss para establecer ZF / PF / CF desde el resultado de la comparación FP (que funciona como las instrucciones de comparación x87 (ver la última sección de esta respuesta), pero en el elemento bajo de las reglas XMM).

Para verificar si no está ordenado, mire PF. Si la comparación está ordenada, puede mirar las otras banderas para ver si los operandos eran mayores, iguales o menores (usando las mismas condiciones que para los enteros sin signo, como jae para Above o Equal).


La instrucción COMISS difiere de la instrucción UCOMISS en que señala una excepción de operación no válida de coma flotante SIMD (#I) cuando un operando fuente es un QNaN o un SNaN. La instrucción UCOMISS señala un no válido excepción numérica solo si un operando de origen es un SNaN.

Normalmente las excepciones FP están enmascaradas, por lo que esto no interrumpe su programa; solo establece el bit en el MXCSR que puede verificar más tarde.

Esto es lo mismo que O/UQ vs. O / US sabores de predicado para cmpps / vcmpps. La versión AVX de las instrucciones cmp[ps][sd] tiene una mayor selección de predicados, por lo que necesitaban una convención de nomenclatura para realizar un seguimiento de ellos.

La O vs. U te dice si el predicado es verdadero cuando los operandos no están ordenados.

La Q vs.S te dice si #I será elevado si cualquiera de los operando es una NaN Silenciosa. # Siempre seré elevado si cualquiera de los operando es una NaN de Señalización, pero esos no son "naturales". No los obtiene como salidas de otras operaciones, solo creando el patrón de bits usted mismo (por ejemplo, como un valor de retorno de error de una función, para garantizar la detección de problemas más adelante).


El equivalente x87 está usando fcom o fucom para establecer la palabra de estado FPU -> fstsw ax -> sahf, o preferiblemente fucomi para establecer EFLAGS directamente como comiss.

La distinción U / no U es la misma con las instrucciones x87 que para comiss / ucomiss

 3
Author: Peter Cordes,
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
2017-05-23 12:32:08

Tal vez esta página en Visual C++ intrínsecos puede ser de ayuda? :)

CMPORDPS

r0 := (a0 ord? b0) ? 0xffffffff : 0x0
r1 := (a1 ord? b1) ? 0xffffffff : 0x0
r2 := (a2 ord? b2) ? 0xffffffff : 0x0
r3 := (a3 ord? b3) ? 0xffffffff : 0x0

CMPUNORDPS

r0 := (a0 unord? b0) ? 0xffffffff : 0x0
r1 := a1 ; r2 := a2 ; r3 := a3
 -3
Author: snemarch,
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
2011-12-24 23:36:03