W nawiązaniu do niektórych poprzednich pytań dotyczących konwersji RGB do RGBA i ARGB BGR, chciałbym przyspieszyć RGB do BGRA konwersji z SSE. Załóżmy maszynę 32-bitową i chcielibyśmy użyć intrinsics. Mam trudności z dopasowaniem buforów źródłowego i docelowego do pracy z rejestrami 128-bitowymi i poszukiwanie innych rozwiązań wektoryzacji.Szybka wektorowy konwersji z RGB do BGRA
Rutynowe być wektorowy jest następujący ...
void RGB8ToBGRX8(int w, const void *in, void *out)
{
int i;
int width = w;
const unsigned char *src= (const unsigned char*) in;
unsigned int *dst= (unsigned int*) out;
unsigned int invalue, outvalue;
for (i=0; i<width; i++, src+=3, dst++)
{
invalue = src[0];
outvalue = (invalue<<16);
invalue = src[1];
outvalue |= (invalue<<8);
invalue = src[2];
outvalue |= (invalue);
*dst = outvalue | 0xff000000;
}
}
Ta rutyna przyzwyczaja primarly dla dużych tekstur (512kB), więc jeśli mogę parallelize niektóre operacje, może być korzystne dla procesu więcej pikseli w podróży. Oczywiście będę musiał profilować. :)
Edit:
Moje argumenty kompilacja ...
gcc -O2 main.c
Czy używasz flagi optymalizacji dla swojego kompilatora (który?)? Kompilator często lepiej zoptymalizuje kod, bez jego wprowadzania. Które dane porównawcze zebrałeś? –
Nie jest to odpowiedź SSE, ale czy próbowałeś rozwinąć swoją pętlę 4 razy, tak aby wejście zawsze zaczynało się od wyrównanego adresu? Następnie możesz odczytać dane wejściowe słowa maszynowego, a nie na przemian, ze specjalnym przesuwaniem i maskowaniem dla każdej względnej pozycji piksela źródłowego. Jak wspomina Dana, warto zobaczyć, jak dobrze kompilator wykonuje wyniki na wysokich poziomach optymalizacji (sprawdź wygenerowany kod asemblera, oprócz testów porównawczych), ale wątpię, czy będzie wystarczająco agresywny, aby rozwinąć pętlę _i_ podzieli punkt wejścia zgodnie z wyrównanie 'in' wszystko samo. –
Świetne pytania. To po prostu "O2" (NIE O3) z GCC4.6. Mój przypadek testowy to przebieg iteracji 10K z 512 jako rozpiętością "szerokości". Dzięki za wspaniałe odpowiedzi! – Rev316