Korzystanie z instrukcji SSE
Mam pętlę napisaną w C ++, która jest wykonywana dla każdego elementu dużej tablicy liczb całkowitych. Wewnątrz pętli maskuję niektóre bity liczby całkowitej, a następnie znajduję wartości minimalne i maksymalne. Słyszałem, że jeśli użyję instrukcji SSE do tych operacji, to będzie działać znacznie szybciej w porównaniu do normalnej pętli napisanej przy użyciu AND i warunków bitowych if-else. Moje pytanie brzmi, czy powinienem skorzystać z tych instrukcji SSE? Co się stanie, jeśli mój kod zostanie uruchomiony na innym procesorze? Czy nadal będzie działać, czy te instrukcje są specyficzne dla procesora?
Nie znaleziono powiązanych wyników
Zaproszony:
Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się
15 odpowiedzi
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
Problemy:
1 Jeśli ścieżka kodu zależy od przetwarzanych danych, implementacja SIMD staje się znacznie trudniejsza. Na przykład:
nie jest to tak łatwe do zrobienia jak SIMD:
2 Jeśli dane nie są ciągłe, ładowanie danych do instrukcji SIMD jest kłopotliwe
Kod 3 jest specyficzny dla procesora. SSE występuje tylko w IA32 (Intel/AMD) i nie wszystkie procesory IA32 obsługują SSE.
Musisz przeanalizować algorytm i dane, aby sprawdzić, czy może to być SSEd, a to wymaga wiedzy, jak działa SSE. Witryna firmy Intel jest pełna dokumentacji.
Anonimowy użytkownik
Potwierdzenie od:
Myślę, że z tego, co opisujesz, twój router prawdopodobnie będzie miał błędy przewidywania gałęzi spowodowane obliczeniami min/max przy użyciu if/else. więc użycie wbudowanych funkcji SIMD pozwoli ci na użycie instrukcji min/max, jednak warto spróbować zamiast tego użyć zdalnego obliczania min/max. W ten sposób można osiągnąć większość wyników przy mniejszym bólu.
Coś w tym stylu:
Anonimowy użytkownik
Potwierdzenie od:
Oznacza to, że x86 wraca do Pentium 2 (nie pamiętam dokładnie, kiedy zostały wprowadzone, ale to było dawno temu)
SSE2, o ile pamiętam, jest tym, który oferuje operacje na liczbach całkowitych, nieco nowszy (Pentium 3? Chociaż wczesne procesory AMD Athlon ich nie obsługiwały)
W każdym razie masz dwie możliwości skorzystania z tych instrukcji. Alternatywnie, napisz cały blok kodu w asemblerze (to prawdopodobnie zły pomysł. Uniemożliwia to kompilatorowi optymalizację kodu, a napisanie wydajnego asemblera jest bardzo trudne).
Użyj również funkcji wewnętrznych dostępnych w kompilatorze (jeśli pamięć się nie zmienia, są one zwykle zdefiniowane w xmmintrin.h)
Ale z drugiej strony wydajność może się nie poprawić. Kod SSE ma dodatkowe wymagania dotyczące przetwarzanych danych. Przede wszystkim należy pamiętać, że dane muszą być wyrównane w granicach 128-bitowych. Między wartościami ładowanymi do tego samego rejestru powinny być również niewielkie lub żadne zależności (128-bitowy rejestr SSE może zawierać 4 int. Dodanie do siebie pierwszej i drugiej nie jest optymalne. Ale dodanie wszystkich czterech int do odpowiedniego 4 int w inny rejestr będzie szybki)
Może być kuszące, aby użyć biblioteki, która opakowuje wszystkie skrzypce SSE niskiego poziomu, ale może to również zrujnować potencjalną przewagę wydajności.
Nie wiem, jak dobra jest obsługa operacji na liczbach całkowitych SSE, więc może to być również czynnik, który może ograniczać wydajność. SSE ma głównie na celu przyspieszenie operacji zmiennoprzecinkowych.
Anonimowy użytkownik
Potwierdzenie od:
http://www.codeproject.com/KB/ recipes/sseintro. aspx
http://www.codeproject.com/KB/ ... .aspx
Anonimowy użytkownik
Potwierdzenie od:
Moja rada dotyczy tego tylko wtedy, gdy naprawdę potrzebujesz zwiększenia wydajności i nie możesz znaleźć funkcji dla swojego problemu w bibliotece takiej jak Intel IPP i jeśli możesz żyć z problemami z przenośnością.
Anonimowy użytkownik
Potwierdzenie od:
Pamiętaj tylko, aby mieć -msse -msse2 w opcjach kompilacji!
Anonimowy użytkownik
Potwierdzenie od:
To powiedziawszy, możesz nie chcieć spędzać czasu na nauce kodowania SSE, jeśli nie znasz jeszcze asemblera x86 - opcją x-simpler może być sprawdzenie dokumentacji kompilatora i sprawdzenie, czy są opcje umożliwiające kompilatorowi automatyczne generowanie kodu SSE dla ty. Niektóre kompilatory bardzo dobrze wektoryzują pętle w ten sposób. (Prawdopodobnie nie będziesz zaskoczony, gdy usłyszysz, że kompilatory Intela są w tym dobre :)
Anonimowy użytkownik
Potwierdzenie od:
A kompilator nie może za każdym razem rozłożyć danych, które działa tak szybko, jak to możliwe.
Ale potrzebujesz dużego doświadczenia, aby przyspieszyć kompilator Intel (jeśli to możliwe).
Anonimowy użytkownik
Potwierdzenie od:
O ile Twoja funkcja nie wymaga przepustowości większej niż 100 000 000 liczb całkowitych na sekundę, SIMD prawdopodobnie nie jest wart zachodu.
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
asembler inline
dla C/C ++, tutaj
artykuł
http://www.ddj.com/cpp/184401967
DDJ. Jeśli nie jesteś pewien, czy Twój program będzie działał na kompatybilnej platformie, powinieneś postępować zgodnie z wytycznymi, które wielu tutaj podało.
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
Zakładam, że moje powiązanie z tym EasySSE jest jasne.
Anonimowy użytkownik
Potwierdzenie od:
Prawdopodobnie znacznie lepiej byłoby, gdybyś pisał bardzo małe pętle i utrzymywał dane bardzo ściśle zorganizowane i polegał tylko na kompilatorze, który zrobi to za Ciebie. Zarówno kompilator Intel C, jak i GCC (od wersji 4.1) mogą automatycznie wektoryzować kod i prawdopodobnie zrobią to lepiej niż Ty. (Po prostu dodaj -ftree-vectorize do swoich CXXFLAGS.)
Edit
: jeszcze jedna rzecz, o której powinienem wspomnieć, to fakt, że niektóre kompilatory obsługują
osadzony
funkcje assemblera, które prawdopodobnie byłyby łatwiejsze w użyciu niż składnia asm () lub __asm {}.