2012-01-31 13 views
17

Powszechną operacją, którą wykonuję w moim programie jest skalowanie wektorów przez skalar (V * s, np. [1,2,3,4] * 2 == [2,4, 6,8]). Czy istnieje instrukcja SSE (lub AVX), aby to zrobić, poza pierwszym ładowaniem skalara w każdej pozycji w wektorze (np. _mm_set_ps (2,2,2,2)), a następnie pomnożenie?SSE (SIMD): pomnóż wektor przez skalarną

To co mam teraz zrobić:

__m128 _scalar = _mm_set_ps(s,s,s,s); 
__m128 _result = _mm_mul_ps(_vector, _scalar); 

szukam czegoś jak ...

__m128 _result = _mm_scale_ps(_vector, s); 

Odpowiedz

13

zależności od kompilatora może być w stanie poprawić generowanie kodu trochę za pomocą _mm_set1_ps:

const __m128 scalar = _mm_set1_ps(s); 
__m128 result = _mm_mul_ps(vector, scalar); 

Jednak skalarne stałe jak to powinno wystarczy być zainicjowane raz, poza wszelkimi pętli, więc wydajność Koszt powinien być nieistotny. (O ile wartość skalarna nie zmienia się w pętli?)

Jak zwykle powinieneś spojrzeć na kod generowany przez kompilator, a także spróbować uruchomić swój kod pod przyzwoitym profilerem, aby zobaczyć, gdzie naprawdę są punkty aktywne.

0

nie wiem jakiejkolwiek pojedynczej instrukcji, dokłada co chcesz. Czy ustawiona operacja naprawdę jest wąskim gardłem? Jeśli mnożysz duży wektor przez tę samą stałą, czas potrzebny do wypełnienia rejestru XMM/YMM czterema kopiami stałej powinien stanowić bardzo mały ułamek całkowitego czasu.

Jako prostą optymalizację, jeśli stała to 2, jak to było w twoim przykładzie, możesz zamiast tego wymieniać mnożenie za pomocą instrukcji dodawania, nie wymagając żadnej stałej.

4

Brak instrukcji na mnożenie wektora przez skalar. Istnieją jednak pewne instrukcje dotyczące ładowania tych samych wartości skalarnych do wszystkich pozycji w rejestrze wektorowym.

zestaw instrukcji AVX zapewnia _mm_broadcast_ss/_mm256_broadcast_ss/_mm256_broadcast_sd intrinsics do wypełniania SSE oraz AVX rejestruje z podwójną wartość sama/pływaka.

W zestawie instrukcji SSE3 można znaleźć wewnętrzny kod _mm_loaddup_pd, który zapełnia rejestr SSE tą samą podwójną wartością.

W innych wersjach SSE zwykle najlepszym rozwiązaniem jest, aby załadować wartości skalarne używając _mm_load_ss/_mm_load_sd a następnie skopiować go do wszystkich elementów rejestru wektora z _mm_shuffle_ps/_mm_unpacklo_pd.

Powiązane problemy