2016-07-08 26 views
18

In https://github.com/numpy/numpy/issues/6428, la causa principale del bug sembra essere che a simd.inc.src:543, un compilatore ottimizza a tmp != 0..I casi in cui float == e! = Non sono opposti diretti

A comment dice che questi "non sono esattamente la stessa cosa". Ma non specifica alcun dettaglio. I NaN sono menzionati più avanti, ma un test mostra che un NaN è paragonabile a 0. il modo previsto.

Quali sono i casi in cui == e != possono entrambi restituire vero/falso?

Oppure la discrepanza è in un altro campo - ad es. restituendo valori che hanno lo stesso valore di verità ma sono diversi come ints (ma il test mostra anche che questo non sembra il caso) ?

+0

Se 'f' può essere' NaN', non è un 'int'. –

+0

Nan non può diventare 0. Poiché 0 è un numero e NaN significa non un numero. quindi stai dicendo se lo fai "int a = 0;" a è un NaN? – amanuel2

+2

Scusami se mi manca qualcosa di ovvio, ma: dove in quel thread lo identificano come la causa principale? Il riferimento più vicino che vedo inizia con "Ho intenzione di indovinare"! Comunque, questo bug collegato sembra più vicino: https://github.com/numpy/numpy/pull/6438 –

risposta

7

Un commento dice che questi "non sono esattamente la stessa cosa". Ma non specifica alcun dettaglio. I NaN sono menzionati più avanti, ma un test mostra che un NaN confronta a 0. il modo previsto.

Quali sono i casi in cui == e! = Possono entrambi restituire vero/falso?

Lo standard dice:

Il == (uguale a) e != (non uguale a) gli operatori sono analoghi agli operatori relazionali tranne loro priorità inferiore. [...] Per qualsiasi coppia di operandi, esattamente una delle relazioni è vera.

(C2011, 6.5.9/3; corsivo)

Pertanto, per qualsiasi espressione X e Y che sono autorizzati congiuntamente come operandi di questi operatori, (X) != (Y) deve valutare allo stesso risultato !((X) == (Y)). Se si trovano in pratica di non farlo, allora il compilatore che ha prodotto quel risultato non è conforme a tale riguardo. Se quella non conformità è inaspettata, allora costituisce un bug nel compilatore.

Inoltre, osservo che 6.5.9/3 si applica tanto a NaN, infiniti e subnormali quanto a qualsiasi altro operando. I NaN sono speciali rispetto a questi operatori per una diversa ragione: i NaNs sono paragonabili a tutti gli operandi, incluso se stessi (supponendo la semantica IEEE).

+1

Ok, sembra che alla fine devo [richiamare l'autore del commento sulla loro dichiarazione] (https://github.com/numpy/numpy/issues/6428#issuecomment-231404458) per porre fine a questa sciarada. –

+1

@ivan_pozdeev Potrebbe essere possibile che il codice sia stato compilato con '-ffast-math' o tale nel qual caso il comportamento potrebbe non essere esattamente corretto. – fuz

+1

@ivan_pozdeev, l'esempio di FUZxxl sarebbe un caso in cui il compilatore non è conforme, ma non è bacato, poiché documenta che l'utilizzo dell'opzione può causare non conformità (ed è anche il motivo per cui il comportamento deve essere esplicitamente abilitato tramite un'opzione) . Si noti che il bug di numpy citato è relativo alla build di MSVC e MSVC è noto per essere non conforme e buggato. –

0

Dalla posta collegato:

Charris commentato 9 Ottobre 2015

ho intenzione di indovinare la !(tmp == 0.) è ottimizzato per tmp != 0., che non è proprio la stessa cosa.

Commento dal PO:

L'autore dice che è una supposizione, ma sono abbastanza positivo che !(tmp==0.) e tmp!=0. non sono equivalenti ed esprimere che, se è risaputo

Come riconciliamo questi due?

Chiaramente, sono logicamente equivalente. Ma per quanto riguarda l'implementazione, potrebbero non esserlo. Un compilatore potrebbe implementare !(a == b) come test a == b seguito da una negazione. In alternativa, potrebbe ottimizzare l'espressione e testare direttamente a != b. Il codice di assemblaggio risultante sarebbe diverso in questi due casi. Lo stesso risultato dovrebbe (deve) essere raggiunto, ma il tempo di esecuzione potrebbe essere diverso.

"non proprio la stessa cosa" sarebbe semplicemente un riconoscimento che !(a == b) e a != b sono in realtà diverse combinazioni di caratteri e il compilatore potrebbe fare qualcosa di tecnicamente diverso con loro, che deve produrre lo stesso risultato. E se si osservano risultati diversi, potrebbe esistere un errore nel compilatore.

+1

Cosa stai dicendo? Devono restituire lo stesso risultato. Il modo in cui arriva la CPU non ha conseguenze. Qualsiasi altra cosa è un bug del compilatore. Quindi "Lo stesso risultato dovrebbe (deve) essere raggiunto, ma il tempo di esecuzione potrebbe essere diverso." - che farebbe fallire così tanti test perché ...? –

+0

@underscore_d Sto dicendo che l'OP ha interpretato erroneamente il commento di "che non è esattamente lo stesso". charris sta parlando delle differenze di implementazione e il PO lo legge come equivalenza logica. Tutto ciò è complicato da una differenza di risultati effettivamente osservata, contrariamente alle aspettative di entrambe le parti. L'OP sta cercando di capire in quale caso l'equivalenza logica si rompe, sulla base del commento di charris. Ma il commento di charris non riguardava l'equivalenza logica dei due test, ma l'implementazione risultante dei test. – AJNeufeld

Problemi correlati