2016-07-08 11 views
18

W https://github.com/numpy/numpy/issues/6428 główną przyczyną błędu wydaje się być, że w simd.inc.src:543, kompilator optymalizuje !(tmp == 0.) do tmp != 0..Przypadki gdzie float == i! = Nie są bezpośrednimi przeciwieństwami

A comment mówi, że są to "nie całkiem to samo". Ale nie podaje żadnych szczegółów. NaNs są wymienione dalej, ale test pokazuje, że NaN porównuje się do 0. w oczekiwany sposób.

Jakie są przypadki, w których == i != mogą zwracać wartość true/false?

Lub rozbieżność występuje w innym polu - np. zwracanie wartości, które mają tę samą wartość prawdy, ale są różne jako ints (ale testy pokazują, że nawet to nie wygląda) ?

+0

Jeśli 'f' może być' NaN', to nie jest 'int'. –

+0

Nan cant zostać 0. Ponieważ 0 jest liczbą, a NaN oznacza nie liczbą. więc twoje powiedzenie jeśli to zrobisz 'int a = 0;' a jest NaN? – amanuel2

+2

Przepraszam, jeśli brakuje mi czegoś oczywistego, ale: gdzie w tym wątku identyfikują to jako główną przyczynę? Najbliższe odwołanie, które widzę zaczyna się od "Zgaduję"! W każdym razie ten połączony błąd wydaje się być bliżej: https://github.com/numpy/numpy/pull/6438 –

Odpowiedz

7

Komentarz mówi, że są to "nie całkiem to samo". Ale nie podaje żadnych szczegółów. NaNs są wymienione dalej, ale test pokazuje, że NaN porównuje się do 0. oczekiwanego sposobu.

Jakie są przypadki, w których == i! = Mogą zwracać true/false?

Norma mówi:

== (równe) i != (nie równy) operatorzy są analogiczne do relacyjnych operatorów z wyjątkiem ich niższym priorytecie. [...] Dla dowolnej pary operandów, dokładnie jedna z relacji jest prawdziwa.

(C2011, 6.5.9/3; nacisk dodano)

Dlatego dla wszystkich wyrażeń X i Y, które są wspólnie dozwolony jako argumenty tych podmiotów, (X) != (Y) musi dawać w wyniku taki sam jak !((X) == (Y)). Jeśli w praktyce okaże się, że nie robią tego, to kompilator, który dał taki wynik, nie jest zgodny pod tym względem. Jeśli ta niezgodność jest nieoczekiwana, oznacza to błąd w kompilatorze.

Dodatkowo zauważam, że 6.5.9/3 odnosi się w równym stopniu do NaN, nieskończoności i podnormałów, jak do wszelkich innych operandów. NaNs są szczególne w odniesieniu do tych operatorów z innego powodu: NaNs porównują nierównolegle do wszystkich operandów, w tym samych siebie (przypuśćmy, że semantyka IEEE).

+1

OK, wygląda na to, że ostatecznie muszę [zadzwonić do autora komentarza na jego wyciągu] (https://github.com/numpy/numpy/issues/6428#issuecomment-231404458), aby zakończyć tę szaradę. –

+1

@ivan_pozdeev Możliwe, że kod jest kompilowany przy użyciu '-ffast-math' lub w takim przypadku zachowanie może nie być prawidłowe. – fuz

+1

@ivan_pozdeev, przykład FUZxxl byłby przypadkiem, w którym kompilator nie jest zgodny, ale nie ma błędów, ponieważ dokumentuje, że użycie tej opcji może spowodować brak zgodności (i to także dlatego zachowanie musi być jawnie włączone za pomocą opcji) . Zauważ, że wspomniany błąd numpy jest związany z kompilacją MSVC, a MSVC jest znany z tego, że jest zarówno niezgodny, jak i błędny. –

0

Od połączonego postu:

charris skomentował 9 paź 2015

Idę do odgadnięcia !(tmp == 0.) jest zoptymalizowany do tmp != 0., który nie jest całkiem to samo.

Komentarz przez OP:

Autor mówi, że to przypuszczenie, ale są one dość pozytywne, że !(tmp==0.) i tmp!=0. nie są równoważne i wyrazić, że jakby to powszechnie wiadomo

Jak czy pogodzimy tych dwóch?

Najwyraźniej są one zgodne z logicznie równoważne z. Ale pod względem implementacji mogą nie być. Kompilator może implementować !(a == b) jako test, po którym następuje negacja. Alternatywnie może zoptymalizować wyrażenie i bezpośrednio przetestować a != b. Wynikowy kod zespołu byłby inny w tych dwóch przypadkach. Ten sam wynik powinien (musi) zostać osiągnięty, ale czas wykonania może być inny.

"Nie całkiem to samo" byłoby po prostu potwierdzeniem, że !(a == b) i a != b są w rzeczywistości różnymi kombinacjami znaków, a kompilator może zrobić z nimi coś technicznie innego, co musi przynieść ten sam wynik. A jeśli zaobserwujemy różne wyniki, może być błąd w kompilatorze.

+1

Co ty mówisz? Muszą zwrócić ten sam wynik. Sposób, w jaki procesor dostaje się tam, nie ma znaczenia. Coś jeszcze jest błędem kompilatora. Następnie "Ten sam wynik powinien (musi) zostać osiągnięty, ale czas wykonania może być inny." - które spowodowałyby, że tak wiele testów zakończy się niepowodzeniem, ponieważ ...? –

+0

@underscore_d Mówię, że OP zinterpretował komentarz Charris "który nie jest taki sam". Charris mówi o różnicach w implementacji, a OP traktuje to jako logiczną równoważność. Wszystko to komplikuje różnica faktycznie obserwowana, wbrew oczekiwaniom obu stron. PO próbuje dowiedzieć się, w jakim przypadku logiczna równoważność załamuje się, na podstawie komentarza Charrisa. Ale komentarz Charrisa nie dotyczył logicznej równoważności dwóch testów, ale wynikającej z nich implementacji testów. – AJNeufeld

Powiązane problemy