Jaki jest najlepszy sposób na załadowanie i zapisanie rejestrów celów generowania do/z rejestrów SIMD? Do tej pory używam tego stosu jako tymczasowy. Na przykład,Najlepszy sposób na załadowanie/zapisanie z/do rejestrów ogólnego przeznaczenia do/z rejestru xmm/mmm
mov [rsp + 0x00], r8
mov [rsp + 0x08], r9
mov [rsp + 0x10], r10
mov [rsp + 0x18], r11
vmovdqa ymm0, [rsp] ; stack is properly aligned first.
Nie sądzę, jest jakaś instrukcja może to zrobić bezpośrednio (lub inny kierunek), ponieważ oznaczałoby to dyspozycję z pięciu argumentów. Jednak powyższy kod wydaje mi się głupi. Czy istnieje lepszy sposób na zrobienie tego? Mogę tylko wymyślić jedną alternatywę, skorzystam z pinsrd
i pokrewnych instrukcji. Ale to nie wydaje się być lepsze.
Motywacją jest to, że czasami szybciej jest robić pewne rzeczy w AVX2, podczas gdy inne mają rejestr ogólnego przeznaczenia. Na przykład, powiedzmy w małym kawałku kodu, istnieją cztery 64-bitowe liczby całkowite bez znaku, potrzebuję czterech xor
, dwóch mulx
z BMI2. Szybsze będzie wykonywanie xor
z vpxor
, jednak nie ma ono odpowiednika AVX2. Jakakolwiek wydajność wzmocnienia vpxor
vs 4 xor
jest tracona z powodu procesu pakowania i rozpakowywania.
Dzięki za szczegółową odpowiedź ponownie. 'xor' jest prawdopodobnie złym przykładem. Faktem jest, że wszystko oprócz 'mulx' może być wykonane z AVX2. Jednak nie wystarczy uzasadnić koszt załadunku/sklepu. Poza tym ładowanie z YMM do r/64 będzie wymagało kilku tasowań/permutacji lub 'pextrq' itd. Chociaż niektóre opóźnienia mogą być ukryte przez przetwarzanie wielu bloków (YMM) w iteracji jednej pętli. Myślę, że muszę po prostu eksperymentować i sam się przekonać. –
@YanZhou: YMM-> liczba całkowita ze składowaniem/ponownym załadowaniem jest znacznie niższym opóźnieniem niż w przeciwnym kierunku, ponieważ przekazywanie do sklepu działa z wyrównanego szerokiego sklepu do wąskich obciążeń, które w pełni pokrywają się z nim. Ponadto obciążenia mają dwukrotnie większą przepustowość niż sklepy. Możliwe, że wydobycie do skalaru na coś może być tego warte, jeśli jest wystarczająco dużo pracy wektorowej. –
@YanZhou: Och, właśnie przypomniałem sobie, że budowanie 64-bitowego wektora mnożącego się z 32-bitowych wektorów mnożnikowych może faktycznie być bardziej wydajne niż przejście do skalarnego iz powrotem. Zobacz [moja odpowiedź na to pytanie] (http://stackoverflow.com/questions/37296289/fastest-way-to-multiply-an-array-of-int64-t) dla wydajnego wektora 64 x 64 => 64bit . Jeśli potrzebujesz wyników w górnej połowie dla wektora 64 x 64 => 128-bitowego, pomnóż, zajmie to dodatkowe instrukcje. (Zapomniałem o ile więcej pracy, może za dużo.) –