2013-03-09 14 views
20

Przystąpiłem do złożenia transcendentalnych funkcji matematycznych biblioteki C z MSVC w trybie fp: strict. Wszystkie wydają się mieć ten sam wzór, oto co się stanie dla sin.Jak ustalić, czy matematyka C używa SSE2?

Najpierw jest procedura wysyłkowa z pliku o nazwie "disp_pentium4.inc". Sprawdza, czy ustawiono zmienną ___use_sse2_mathfcns; jeśli tak, wywołuje __sin_pentium4, w przeciwnym razie wywołuje __sin_default.

__sin_pentium4 (w "sin_pentium4.asm") rozpoczyna się od przeniesienia argumentu z x87 fpu do rejestru xmm0, wykonuje obliczenia za pomocą instrukcji SSE2 i ładuje wynik z powrotem do fpu.

__sin_default (w "sin.asm") utrzymuje zmienną na stosie x87 i po prostu wywołuje fsin.

W obu przypadkach operand jest pchany na stosie x87 i zwracany na nim, dzięki czemu jest on przezroczysty dla osoby dzwoniącej, ale jeśli zdefiniowano ___use_sse2_mathfcns, operacja jest faktycznie wykonywana w SSE2 zamiast x87.

To zachowanie jest dla mnie bardzo interesujące, ponieważ funkcje transcendentalne x87 są znane z nieco innych zachowań w zależności od implementacji, podczas gdy dany fragment kodu SSE2 powinien zawsze dawać odtwarzalne wyniki.

Czy istnieje sposób, aby ustalić, na pewno, podczas kompilacji lub wykonywania, że ​​ścieżka kodu SSE2 zostanie wykorzystana? Nie jestem biegle piszącym zespołem, więc jeśli dotyczy to pisania jakiegokolwiek zespołu, przykład kodu będzie mile widziany.

+0

W jakim katalogu znajdują się te pliki? –

+0

"f: \ dd \ vctools \ crt_bld \ SELF_X86 \ crt \ prebuild \ tran \ i386 \" - to jest to, co widzę w procesie demontażu, nie mam plików samodzielnie. – Asik

+2

Nie, niemożliwe, przyzwoite pytanie na temat SO ... Czuję zażartą chęć przegłosowania. –

Odpowiedz

7

Znalazłem odpowiedź poprzez dokładne zbadanie math.h. Jest to kontrolowane przez metodę o nazwie _set_SSE2_enable.Jest to symbol publiczny udokumentowane here:

Włącza lub wyłącza użycie Streaming SIMD Extensions 2 (SSE2) instrukcję CRT procedur matematycznych. (Ta funkcja nie jest dostępna na architekturach x64 ponieważ SSE2 jest domyślnie włączona.)

Powoduje aforementionned flagę ___use_sse2_mathfcns być ustawiony na podanej wartości, skutecznie włączając lub wyłączając wykorzystania procedur _pentium4 SSE2.

Dokumentacja wspomina, że ​​ma to wpływ tylko na pewne funkcje transcendentalne, ale patrząc na demontaż, wydaje się, że dotyczy to każdego z nich.

Edit: wchodząc do każdej funkcji wynika, że ​​wszystkie one są dostępne w SSE2 z wyjątkiem następujących:

  • FMOD
  • sinh
  • cosh
  • tanh
  • sqrt

Sqrt to największy sprawca, ale nie jest łatwo w SSE2 za pomocą intrinsics. Dla innych nie ma prostego rozwiązania, z wyjątkiem może korzystania z biblioteki innej firmy, ale prawdopodobnie mogę obejść się bez niej.

2

Krótka odpowiedź brzmi, że nie można powiedzieć W SWOIM KODZE, aby dowiedzieć się, co zrobi biblioteka, chyba że dotyczą one również szczegółowych informacji dotyczących implementacji biblioteki. To spowodowałoby, że kod byłby zupełnie niepoprawny - nawet dwie różne kompilacje tego samego kompilatora mogą zmienić wnętrze biblioteki.

Oczywiście, jeśli przenośność nie jest problemem, to użycie opcji extern <type> ___use_sse2_mathfcns; i sprawdzenie, czy to prawda, wyraźnie działałoby.

Spodziewam się, że jeśli procesor ma SSE2 i korzystasz z nowoczesnej biblioteki, używałby SSE2 wszędzie tam, gdzie to możliwe. Ale mówienie, że na pewno to inna sprawa.

Jeśli ma to krytyczne znaczenie dla kodu, należy wdrożyć własne funkcje transcendentalne i używać ich - to jedyny sposób na zagwarantowanie tego samego wyniku. Lub użyj jakiegoś odpowiedniego wbudowanego asemblera (lub transcendentalnego) kodu do obliczenia wybranych wartości sin, cos, itp. I porównaj te z funkcjami sin() i cos() dostarczonymi przez bibliotekę.

+0

'extern int ___ use_sse2_mathfcns' daje mi błąd linkera. Nie wiem, gdzie to jest zdefiniowane, to tylko nazwa w rozkładzie. – Asik

+0

Spróbuj z jednym mniejszym "_"? –

+0

To też nie działa. – Asik

3

Dlaczego nie używać własnej biblioteki zamiast środowiska wykonawczego C? Zapewniłoby to jeszcze silniejszą gwarancję spójności między komputerami (prawdopodobnie środowisko wykonawcze C jest dostarczane jako biblioteka DLL i może nieznacznie zmienić się w czasie).

Polecam CRlibm. Jeśli już celujesz w SSE2 i tak długo, jak nie zamierzałeś zmieniać trybu zaokrąglania FPU, jesteś w idealnych warunkach, aby z niego skorzystać i nie znajdziesz dokładniejszej implementacji.

+0

Rzeczywiście muszę ustawić precyzję i zaokrąglenie FPU: 53-bitowe i round-to-nearest. Nie powinno to mieć miejsca w przypadku procedur CRlibm, jeśli są one implementowane w SSE2. – Asik

+0

@Dr_Asik Tryb emulacji instrukcji stosu punktów zmiennych nie jest doskonały: w przypadku ustawienia na 53-bitową istotność, wykładnik zachowuje swój pełny rozszerzony zakres. W szczególności trudne jest unikanie podwójnych zaokrągleń. Mimo to CRlibm jest przeznaczony do pracy nawet podczas kierowania na x87, o ile jest ustawiony w trybie emulacji, do którego odwołujesz się: http://lipforge.ens-lyon.fr/www/crlibm/start.html –

+1

+1 dla CRLibM. Oprócz gwarantowanej doskonałej dokładności zwykle jest to szybsze niż GNU LibM i Cephes C. Jeśli chcesz wymienić trochę dokładności na wydajność, spójrz na FDLibM. –

Powiązane problemy