2012-02-23 18 views
12

Po zapoznaniu się z tematem, istnieje wiele dowodów z wielu źródeł, że używanie standardowych rzutów C lub C++ do konwersji z liczb zmiennoprzecinkowych na liczby całkowite na Intel jest bardzo powolne. Aby spełnić specyfikację ANSI/ISO, procesory Intela muszą wykonać wiele instrukcji, w tym te potrzebne do przełączenia trybu zaokrąglania sprzętu FPU.Jak zapewnić, że wydruk jest inline w gcc?

W różnych dokumentach opisano kilka obejść, ale najczystszym i najbardziej przenośnym wydaje się być połączenie lrint() dodane do standardów C99 i C++ 0x. Wiele dokumentów mówi, że kompilator powinien rozszerzać te funkcje, gdy włączona jest optymalizacja, prowadząc do kodu, który jest szybszy niż konwencjonalny rzut lub wywołanie funkcji.

Znalazłem nawet odniesienia do worków śledzenia cech gcc, aby dodać tę wbudowaną ekspansję do optymalizatora gcc, ale w moich własnych testach wydajności nie mogłem go uruchomić. Wszystkie moje próby pokazują, że wydajność drukowania jest znacznie wolniejsza niż zwykła obsada stylu C lub C++. Analiza wyjścia zespołu kompilatora i rozmontowanie skompilowanych obiektów zawsze pokazuje jawne wywołanie zewnętrznej funkcji lrint() lub lrintf().

Wersje gcc, nad którymi pracowałem, to: 4.4.3 i 4.6.1, a także wypróbowałem wiele kombinacji flag w 32-bitowych i 64-bitowych miejscach docelowych x86, w tym opcje umożliwiające jawne włączenie SSE.

Jak uzyskać dostęp do gcc w linii rozwijanej lrint i uzyskać szybką konwersję?

+1

Czy rzeczywiście wyprofilowałeś i potwierdziłeś, że używanie oczywistych rzutów znaczna część środowiska wykonawczego twojego programu? –

+2

Profilowanie pokazuje, że mogę uzyskać różnicę prędkości 2-4%, używając ręcznie napisanego makra asemblera unoszonego z artykułu. Jest to opłacalne, ponieważ obliczenia wykonywane są między ramkami aplikacji do renderowania 3D. –

+1

czy ustawiłeś '-fno-math-errno'? powinieneś także rozważyć użycie '-ffast-math', która nie zawsze jest opcją, jeśli polegasz na specyficznej selekcji fp ... – Christoph

Odpowiedz

10

Funkcja lrint() może powodować błędy w domenie i zakresie. Jednym z możliwych sposobów, w jaki libc radzi sobie z takimi błędami, jest ustawienie errno (patrz C99/C11 sekcja 7.12.1). Narzut sprawdzania błędów może być dość znaczący iw tym konkretnym przypadku wydaje się wystarczający, aby optymalizator zdecydował się na inline.

Flaga gcc -fno-math-errno (która jest częścią -ffast-math) wyłącza te kontrole. Dobrym pomysłem może być zaglądanie do -ffast-math, jeśli nie polegasz na standardowej obsłudze semantycznej zmiennoprzecinkowej, w szczególności NaN i nieskończoności ...

0

Czy wypróbowałeś flagę -finline-functions do gcc.

Można również bezpośredni GCC próbować zintegrować wszystkie „dość proste” funkcje do swoich rozmówców z opcją -finline-functions.

zobaczyć http://gcc.gnu.org/onlinedocs/gcc/Inline.html

Tutaj można powiedzieć, gcc, aby wszystkie funkcję inline ale nie wszystkie zostanie wstawiony. Kompilator używa heurystyki do określenia, czy ta funkcja jest wystarczająco mała, aby można ją było wstawić. Jedną z rzeczy jest to, że funkcjanie będzie tu wstawiana.

+0

Próbowałem -finline-funkcje i nie ma znaczenia dla wyjścia kompilatora. –

+0

jeśli używasz lrint() biblioteki matematyki w kodzie i kompilowanie go przez gcc potem lrint() nie będzie inlined bo w twoim przypadku będzie to pochodzi z binarnym połączonej biblioteki. Kod lrint() nie będzie inlined tutaj –

+0

Dokument ten wskazuje inaczej: „http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html funkcjami ISO C99 ..... lrintf, lrintl, lrint ...... są traktowane jako wbudowanych funkcji poza ścisłym trybie ISO C90 (-ansi lub -std = C90).” Dalej do góry dokumentu to mówi: „Wiele z tych funkcji są zoptymalizowane tylko w niektórych przypadkach, jeśli nie są one zoptymalizowane w konkretnym przypadku będą emitowane wywołanie funkcji biblioteki” ale nie byłem w stanie opracować przypadku, w którym są zoptymalizowane. –

Powiązane problemy