Wstawki asm w c++ w net 2003

0

Witam
Chciałem przyspieszyc troche program i dodałem wstawki asemblerowe nie znam się na tym zabardzo. I o dziwo zwolniło ;) coś poknociłem albo gdzieś coś trzeba jeszcze ustawić by było szybciej - jak możecie to pomóżcie. Tu jest fragemt kodu.
ASM

<i>		DWORD rgba[4] = {124,54,12,255};
		DWORD tab[4];
		__asm
		{
			mov edi, p
			mov esi, 8
			mov eax, rgba
			mov ebx, [rgba + 4]
			mov ecx, [rgba + 8]
			mov edx, [rgba + 12]
			imul eax, edi
			imul ebx, edi
			imul ecx, edi
			imul edx, edi
			shr eax, 8
			shr ebx, 8
			shr ecx, 8
			shr edx, 8
			mov tab, eax
			mov [tab + 4], ebx
			mov [tab + 8], ecx
			mov [tab + 12], edx
		};</i>

i ten sam szybszy kod w c++
DWORD rgba[4] = {124,54,12,255};
DWORD tab[4];
tab[ 0 ] = MUL2( rgba[ 0 ], p );
tab[ 1 ] = MUL2( rgba[ 1 ], p );
tab[ 2 ] = MUL2( rgba[ 2 ], p );
tab[ 3 ] = MUL2( rgba[ 3 ], p );

gdzie MUL2 to makro
#define MUL2(a,b) (((a)*(b))>>8)
Poza tym kodem jest dosyć duża pętla - znacyz kod jest troche skrócony by było łatwiej załapać. Tak wygląda w programie testowym bo coś mi nie grało wiec wyciołem sobie i odnawia tą pętle kilka tysięcy razy.

0

dwie rzeczy: ile p wynosi i dlaczego rgba to DWORD /z nazwy wnioskuję, ze to pixel 32bit/. Jeżeli to pixel /w prawidłowym zapisie - 4x BYTE albo lepiej nawet 4x WORD/ to ładnie można to rozpisać na mmx\sse...

0

tu aukrat nie mam pomyłki DWORD ma być dlatego ze to jest uśrednianie koloru normalnie powinno być np.
float p = 0.5;
BYTE rgba[4]
i wtedy przy mnożeniu przez p wychodzi 50% koloru, aby to przyspieszyc zrobiłem to na zmiennych stało przecinkowcyh czyli przy pomocy przesunieć bitowych. p też jest DWORD równe 128 bo przesóam o 8 bitów.
Samo działanie w sęsie czy jes dobze czy nie jest ok bez zarzutów ale wolno wolniej niż w C wiec przypuszczam ze czegoś nie właczyłem - jakiegoś wspomagania dla asm w ustawieniach projektu lub czegoś tam.

0

tu aukrat nie mam pomyłki DWORD ma być dlatego ze to jest uśrednianie koloru normalnie powinno być np.
float p = 0.5;
BYTE rgba[4]
i wtedy przy mnożeniu przez p wychodzi 50% koloru, aby to przyspieszyc zrobiłem to na zmiennych stało przecinkowcyh czyli przy pomocy przesunieć bitowych. p też jest DWORD równe 128 bo przesóam o 8 bitów.
Samo działanie w sęsie czy jes dobze czy nie jest ok bez zarzutów ale wolno wolniej niż w C wiec przypuszczam ze czegoś nie właczyłem - jakiegoś wspomagania dla asm w ustawieniach projektu lub czegoś tam.

0
egon26 napisał(a)

p też jest DWORD równe 128
kod:

        imul     reg32, p
        shr      reg32, 8 

o jasny gwint... człowieku! Mnożenie przez potęgi 2 to przesunięcie bitowe! Mnożenie przez 128 to << 7; Przecież "<< 7" + " >> 8" -> " >> 1 " w sumie to chyba logiczne, że jak dzielisz przez 2 to mnożysz przez 0.5... czyli przesuwasz bitowo w prawo o 1. Kompilator to wyłapał, dlatego jego kod jest szybszy. Twój kod po poprawkach:

        lea     esi, [rgba]
        lea     edi, [tab]
        mov     eax, [esi]
        mov     ebx, [esi+4]
        mov     ecx, [esi+8]
        mov     edx, [esi+12]
        shr     eax, 1
        shr     ebx, 1
        shr     ecx, 1
        shr     edx, 1
        mov     [edi], eax
        mov     [edi+4], ebx
        mov     [edi+8], ecx
        mov     [edi+12], edx  

Albo lepiej na mmx:

        movq    mm0, [esi]
        movq    mm1, [esi+8]
        psrld   mm0, 1
        psrld   mm1, 1
        movq    [edi], mm0
        movq    [edi+8], mm1 

Tylko po zakończeniu operacji na mmx zrób

        emms

aby wyczyścić co trzeba - inaczej operacje na koprocesorze skończą się wyjątkiem. Zamist konwertować 1 piksel konwertuj po 4 w jednym przebiegu pętli. W sumie to na SSE2 można i po 8 pikseli w ten sposób konwertować... ale do tego trzeba co najmniej P4.

egon26 napisał(a)

...wolniej niż w C wiec przypuszczam ze czegoś nie właczyłem - jakiegoś wspomagania dla asm w ustawieniach projektu lub czegoś tam.
Nie włączyłeś znajomości logiki binarnej... ale powiedzmy, że to ze zmęczenia :-) jak 'coś' to przygotowanie danych to takiego przetwarzania i cały algorytm można zrobić na mmx, gdybyś był zainteresowany - pisz. Będzie bardzo szybkie :>
Edit:
Możesz przecież jak stosujesz rgba nadal używać tablicy 4 bajtów, wtedy będzie jeszcze szybsze bo odpadnie konwersja tablic /chyba ją robisz, przynajmniej tak mi się wydaje/ a na jednym rejestrze mmx będzie można konwertować po 2 piksele - instrukcja psrlb. Ogólnie - takie rzeczy albo pisze się w całości na instrukcjach standardowych albo na mmx/sse.

0

Sorki ze teraz dopiero pisze - przez pare dni nie chciała mi się załadować ta strona.
No na asm znam się bardzo sałabo ;) ale p = 128 to było na przykład;) p nie jest stałe niestety. Zaraz spróbuje zastosować twój kod do mojego problemu i dam znać czy coś poszło ;) </b>

1 użytkowników online, w tym zalogowanych: 0, gości: 1