Postanowiłem kontynuować szybką optymalizację narożników i utknąć na _mm_movemask_epi8
instrukcji SSE. Jak mogę przepisać to na ARM Neon z wejściem uint8x16_t
?SSE _mm_movemask_epi8 Równoważna metoda dla ARM NEON
Odpowiedz
po kilku testach wygląda na to następujący kod działa popraw:
int32_t _mm_movemask_epi8_neon(uint8x16_t input)
{
const int8_t __attribute__ ((aligned (16))) xr[8] = {-7,-6,-5,-4,-3,-2,-1,0};
uint8x8_t mask_and = vdup_n_u8(0x80);
int8x8_t mask_shift = vld1_s8(xr);
uint8x8_t lo = vget_low_u8(input);
uint8x8_t hi = vget_high_u8(input);
lo = vand_u8(lo, mask_and);
lo = vshl_u8(lo, mask_shift);
hi = vand_u8(hi, mask_and);
hi = vshl_u8(hi, mask_shift);
lo = vpadd_u8(lo,lo);
lo = vpadd_u8(lo,lo);
lo = vpadd_u8(lo,lo);
hi = vpadd_u8(hi,hi);
hi = vpadd_u8(hi,hi);
hi = vpadd_u8(hi,hi);
return ((hi[0] << 8) | (lo[0] & 0xFF));
}
Zauważ, że nie testowałem żadnej z tego, ale coś takiego może działać:
X := the vector that you want to create the mask from
A := 0x808080808080...
B := 0x00FFFEFDFCFB... (i.e. 0,-1,-2,-3,...)
X = vand_u8(X, A); // Keep d7 of each byte in X
X = vshl_u8(X, B); // X[7]>>=0; X[6]>>=1; X[5]>>=2; ...
// Each byte of X now contains its msb shifted 7-N bits to the right, where N
// is the byte index.
// Do 3 pairwise adds in order to pack all these into X[0]
X = vpadd_u8(X, X);
X = vpadd_u8(X, X);
X = vpadd_u8(X, X);
// X[0] should now contain the mask. Clear the remaining bytes if necessary
To musiałyby być powtarzane raz przetworzyć 128-bitowy wektor, ponieważ vpadd
działa tylko na 64 lat -bitowe wektory.
Znam ten post jest dość przestarzały, ale uważam, że warto dać (zatwierdzone) rozwiązanie mojego. Przyjmuje wszystkie zera/wszystkie zera na każdym z pasm argumentu Input.
const uint8_t __attribute__ ((aligned (16))) _Powers[16]=
{ 1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128 };
// Set the powers of 2 (do it once for all, if applicable)
uint8x16_t Powers= vld1q_u8(_Powers);
// Compute the mask from the input
uint64x2_t Mask= vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(vandq_u8(Input, Powers))));
// Get the resulting bytes
uint16_t Output;
vst1q_lane_u8((uint8_t*)&Output + 0, (uint8x16_t)Mask, 0);
vst1q_lane_u8((uint8_t*)&Output + 1, (uint8x16_t)Mask, 8);
(umysł http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47553, w każdym razie).
Podobnie jak Michael, sztuką jest stworzenie uprawnienia indeksów tych wpisów niż null i podsumować je parami trzy razy. Należy to zrobić, zwiększając rozmiar danych, aby podwoić krok przy każdym dodaniu. Zmniejszasz z 2 8 8-bitowych wpisów do 2 x 4 16-bitowych, a następnie 2 x 2 32-bitowych i 2 x 1 64-bitowych. Niski bajt tych dwóch liczb daje rozwiązanie. Nie sądzę, że istnieje prosty sposób na spakowanie ich w jedną krótką wartość za pomocą NEON.
Wykonuje 6 instrukcji NEON, jeśli wejście jest w odpowiedniej formie, a moce mogą być wstępnie ładowane.
- 1. ARM NEON awaria wektoryzacja
- 2. ARM NEON SIMD wersja 2
- 3. NEON kontra Intel SSE - równoważność niektórych operacji
- 4. ARM NEON: porównanie wartości 128-bitowych
- 5. Metoda równoważna z odpowiednikiem -respondsToSelector:
- 6. Czy istnieje metoda równoważna LINQ?
- 7. Problemy z dwurdzeniowym kodem ARM NEON Qualcomm Scorpion?
- 8. ARM NEON: Jaka jest różnica między vld4_f32 a vld4q_f32?
- 9. ARM NEON montaż na Windows Phone 8 nie działa
- 10. Równoważna metoda dla pokazu w opencv Java build
- 11. LLVM opcji budowania dla ARM/Raspberry Pi
- 12. Funkcja równoważna dla xticks dla obiektu AxesSubplot
- 13. W RSpec, czy istnieje metoda równoważna "unstub", ale "should_receive"?
- 14. Neonowy odpowiednik SSE intrinsics
- 15. Jak zmienić kolejność danych wektorowych za pomocą elementów wewnętrznych ARM Neon?
- 16. Czy istnieje metoda Java Stream równoważna kolekcjom Scali "collect"?
- 17. Tworzenie SDL dla ARM przy użyciu samodzielnego toolchaina dla Androida
- 18. Jak zoptymalizować zapętlone mnożenie macierzy wektorowej 4D za pomocą ARM NEON?
- 19. Uruchamianie plików binarnych ARM dla Androida w systemie Linux ARM
- 20. Kompilator Ada dla procesorów Arm
- 21. Krzyż kompilacji helloworld dla ARM
- 22. SSE powrót rejestr z SSE niepełnosprawnych
- 23. Stała poza zasięgiem z intrinsics NEON
- 24. Równoważna nazwa Golang.txt
- 25. Uniwersalny kod binarny dla różnych wersji SSE
- 26. Biblioteki matematyczne SIMD dla SSE i AVX
- 27. Android ARMv6/v7 i VFP/NEON
- 28. Python Równoważna do phpinfo()
- 29. SSE z podziałem całkowitym?
- 30. Kompilacja krzyżowa dla ARM z Autoconf
Witam @Michael thanx na przykład. czy możesz wyjaśnić, w jaki sposób mogę wypełnić wektor B wymaganymi bajtami? dla A mogę używać vdup_n_u8 (0x80), ale jak mam to zrobić dla A? również piszesz vshl_u8, ale w komentarzu jest odpowiednia zmiana? – inspirit
Aby zainicjować wektor B: 'vld1' z tablicy stałej (?). O prawej zmianie: dokumentacja ARM stwierdza _ "Jeśli wartość przesunięcia jest dodatnia, operacja jest przesunięciem w lewo, w przeciwnym razie jest to przesunięcie w prawo." _. Nie jestem do końca pewien, czy tak jest w przypadku, gdy przenoszone dane to 'u8', czy też musisz użyć' s8'. – Michael
Tak, rozumiem, że muszę załadować B z tablicy i zastanawiałem się nad dostarczonymi wartościami w tym wektorze. możesz być bardziej konkretny na ten temat? powinno być tylko [0, -1, -2, -3, -4, -5, -6, -7]? i tak, potrzebuję go do wektora danych u8 w tej chwili – inspirit