LÖST Inline assembleroptimering. Hjälp!

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 6921
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

LÖST Inline assembleroptimering. Hjälp!

Inlägg av Marta »

När gcc kompilerar dessa stackars rader C så spyr den ut ett förfärande härke.

Tack vare moderna processorers brutala kraft funkar det drägligt ändå, men skulle vilja ha dessa 6 rader optimerat som inline assembler.

Skulle nog kunna krafsa ihop något själv, men hur får jag fatt i ingångsvärdena och pekaren för resultatet? Det ser ut att ligga som registervariabler och det är ju bra, men kan inget om inline asm i gcc.

Kod: Markera allt

        for (y = rows; y > 0; y--) {                    //rows
          for (x = colw; x > 0; x--) {                  //columns
            mask=*fc_p++;                               //get pixel from cache
            (*p)&=~mask;                                //punch a hole in bkgnd
            (*p++)|=mask&fg;                            //fill with fg and nxt column
          };
          p+=pmx-colw;                                  //nxt row
        };

 370:              ****         for (y = rows; y > 0; y--) {                    //rows
 993                            .loc 1 370 9
 994 0868 8B45AC                movl    -84(%rbp), %eax
 995 086b 4898                  cltq
 996 086d 488945F0              movq    %rax, -16(%rbp)
 997                            .loc 1 370 2
 998 0871 EB71                  jmp     .L38
 999                    .L41:
 371:              ****           for (x = colw; x > 0; x--) {                  //columns
 1000                           .loc 1 371 11
 1001 0873 8B45A8               movl    -88(%rbp), %eax
 1002 0876 4898                 cltq
 1003 0878 488945F8             movq    %rax, -8(%rbp)
 1004                           .loc 1 371 4
 1005 087c EB47                 jmp     .L39
 1006                   .L40:
 372:              ****             mask=*fc_p++; //fc_p++;                     //get pixel from cache
 1007                           .loc 1 372 16 discriminator 3
 1008 087e 488B45C8             movq    -56(%rbp), %rax
 1009 0882 488D5004             leaq    4(%rax), %rdx
 1010 0886 488955C8             movq    %rdx, -56(%rbp)
 1011                           .loc 1 372 11 discriminator 3
 1012 088a 8B00                 movl    (%rax), %eax
 1013                           .loc 1 372 10 discriminator 3
 1014 088c 89459C               movl    %eax, -100(%rbp)
 373:              ****             (*p)&=~mask;                                //punch a hole in bkgnd
 1015                           .loc 1 373 10 discriminator 3
 1016 088f 488B45D0             movq    -48(%rbp), %rax
 1017 0893 8B00                 movl    (%rax), %eax
 1018 0895 89C2                 movl    %eax, %edx
 1019                           .loc 1 373 12 discriminator 3
 1020 0897 8B459C               movl    -100(%rbp), %eax
 1021 089a F7D0                 notl    %eax
 1022                           .loc 1 373 10 discriminator 3
 1023 089c 21D0                 andl    %edx, %eax
 1024 089e 89C2                 movl    %eax, %edx
 1025 08a0 488B45D0             movq    -48(%rbp), %rax
 1026 08a4 8910                 movl    %edx, (%rax)
 374:              ****             (*p++)|=mask&fg;                            //put fg and nxt column
 1027                           .loc 1 374 9 discriminator 3
 1028 08a6 488B45D0             movq    -48(%rbp), %rax
 1029 08aa 488D5004             leaq    4(%rax), %rdx
 1030 08ae 488955D0             movq    %rdx, -48(%rbp)
 1031                           .loc 1 374 12 discriminator 3
 1032 08b2 8B10                 movl    (%rax), %edx
 1033 08b4 89D1                 movl    %edx, %ecx
 1034                           .loc 1 374 18 discriminator 3
 1035 08b6 8B55B4               movl    -76(%rbp), %edx
 1036 08b9 23559C               andl    -100(%rbp), %edx
 1037                           .loc 1 374 12 discriminator 3
 1038 08bc 09CA                 orl     %ecx, %edx
 1039 08be 8910                 movl    %edx, (%rax)
 371:              ****             mask=*fc_p++; //fc_p++;                     //get pixel from cache
 1040                           .loc 1 371 27 discriminator 3
 1041 08c0 48836DF8             subq    $1, -8(%rbp)
 1041      01
 1042                   .L39:
 371:              ****             mask=*fc_p++; //fc_p++;                     //get pixel from cache
 1043                           .loc 1 371 4 discriminator 1
 1044 08c5 48837DF8             cmpq    $0, -8(%rbp)
 1044      00
 1045 08ca 75B2                 jne     .L40
 375:              ****           };
 376:              ****           p+=pmx-colw;                                  //nxt row
 1046                           .loc 1 376 10 discriminator 2
 1047 08cc 8B050000             movl    pmx(%rip), %eax
 1047      0000
 1048 08d2 2B45A8               subl    -88(%rbp), %eax
 1049 08d5 4898                 cltq
 1050                           .loc 1 376 5 discriminator 2
 1051 08d7 48C1E002             salq    $2, %rax
 1052 08db 480145D0             addq    %rax, -48(%rbp)
 370:              ****           for (x = colw; x > 0; x--) {                  //columns
 1053                           .loc 1 370 25 discriminator 2
 1054 08df 48836DF0             subq    $1, -16(%rbp)
 1054      01
 1055                   .L38:
 370:              ****           for (x = colw; x > 0; x--) {                  //columns
 1056                           .loc 1 370 2 discriminator 1
 1057 08e4 48837DF0             cmpq    $0, -16(%rbp)
 1057      00
 1058 08e9 7588                 jne     .L41
 336:              ****                                                 //yes
 1059                           .loc 1 336 10
 1060 08eb E9FE0300             jmp     .L55
 1060      00
 1061                   .L37:
 377:         ĸs
      ****         };
Senast redigerad av Marta 21 oktober 2022, 12:46:59, redigerad totalt 1 gång.
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1339
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Re: Inline assembleroptimering. Hjälp!

Inlägg av baron3d »

Inte något svar. Vad har du satt optimeringen till?
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 6921
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: Inline assembleroptimering. Hjälp!

Inlägg av Marta »

Det är default optimering, inget specificerat.

gcc -c -g -Wa,-a,-ad infile.c > listfile.txt
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1339
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Re: Inline assembleroptimering. Hjälp!

Inlägg av baron3d »

-O[n] n controls the optimization level.
n = 0 No optimization, the default setting if no -O appears
n = 1 Normal optimization, the default if you specify -O without an operand.
n = 2 Extensive optimization
n = 3 Extensive optimization with automatic inlining of subprograms not specified by pragma Inline. This applies only to inlining within a unit.

Så prova med -O1 eller -O2.
Nerre
Inlägg: 26697
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Inline assembleroptimering. Hjälp!

Inlägg av Nerre »

-O1 är ju default, du menar väl -O2 eller -O3?
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Inline assembleroptimering. Hjälp!

Inlägg av Mr Andersson »

Om du inte anger något -O alls får du O0. Det får väl ändå ses som default?
Om du skriver -O utan siffra så blir det O1.
Nerre
Inlägg: 26697
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Inline assembleroptimering. Hjälp!

Inlägg av Nerre »

Ah, jag läste slarvigt.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45265
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Inline assembleroptimering. Hjälp!

Inlägg av TomasL »

Tänk dock på att ju högre optimering, desto svårare (och i vissa lägen omöjligt) att debugga.
BJ
Inlägg: 8218
Blev medlem: 11 april 2007, 08:14:53
Ort: En_stad

Re: Inline assembleroptimering. Hjälp!

Inlägg av BJ »

Och ibland hjälper det inte så mycket med optimering.
Jag har sett c-program som t.ex. kopierar lite bitar
mellan register. Kompilatorn gjorde något ganska långt
och krångligt, som hade blivit kortare och snabbare
om man hade skrivit det för hand i assembler direkt.
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 6921
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: Inline assembleroptimering. Hjälp!

Inlägg av Marta »

Nedanstående fungerar, men är inte färdigt. Looparna skall givetvis också in som asm.

Får inte till det med utgångsvärden, blir olika magiska fel... Här är pekarna "void" efteråt då looparna inkluderats, men det vore bra att kunna till ett annat tillfäle.

Hur sätter jag en label att hoppa till? Skall finnas överst i asm.

Kan rows och colw enumreras sist i inputraden även om de ligger först i koden?

Kod: Markera allt

        for (y = rows; y > 0; y--) {                    //rows
          for (x = colw; x > 0; x--) {                  //columns

            asm ( "movl (%0), %%eax\n\t"                //get inverted pixel from cache
                  "add  $4, %0\n\t"                     //nxt pos
                  "andl %%eax, (%1)\n\t"                //punch a hole in bkgnd
                  "notl %%eax\n\t"                      //un-invert pixel
                  "andl %2, %%eax\n\t"                  //put fg
                  "orl  %%eax, (%1)\n\t"
                  "add  $4, %1\n\t"                     //nxt column
                  : //removed "=0"(fc_p), "=1"(p)
                  : "r"(fc_p), "r"(p), "r"(fg)
                  : "%eax"
                );
                fc_p++; p++;                            //output fails, removed, this for test

//            mask=*fc_p++; //fc_p++;                     //get pixel from cache
//            (*p)&=~mask;                                //punch a hole in bkgnd
//            (*p++)|=mask&fg;                            //put fg and nxt column
          };
          p+=pmx-colw;                                  //nxt row
        };
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 6921
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av Marta »

Såhär blev det, bra mycket kortare än det gcc kräkte upp.
Jag vet det inte är exakt samma, är rows eller colw redan noll vid start så hanteras det inte, men då kommer det här aldrig att exekveras så det betyder inget just här.

Kod: Markera allt

            rowofs=(pmx-colw)*4;
            asm (       "movl %4, %%edx\n\t"            //keep column loop init
                 "LLL1:\n\t"
                        "movl (%0), %%eax\n\t"          //get inverted pixel from cache
                        "add  $4, %0\n\t"               //nxt pos
                        "andl %%eax, (%1)\n\t"          //punch a hole in bkgnd
                        "notl %%eax\n\t"                //un-invert pixel
                        "andl %2, %%eax\n\t"            //put fg
                        "orl  %%eax, (%1)\n\t"
                        "add  $4, %1\n\t"               //nxt column
                        "subl $1, %4\n\t"               //count down columns
                        "jnz  LLL1\n\t"                 //not zero, nxt loop
                        "add  %5, %1\n\t"               //pnt to nxt row
                        "movl %%edx, %4\n\t"            //re-init column loop
                        "subl $1, %3\n\t"               //count down rows
                        "jnz  LLL1\n\t"                 //not zero, nxt loop
                  :
                  //       0       1        2          3          4            5
                  : "r"(fc_p), "r"(p), "r"(fg), "r"(rows), "r"(colw), "r"(rowofs)
                  : "%eax", "%edx", "0", "1", "3", "4"
                );
hummel
Inlägg: 2267
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av hummel »

Hur stor blev prestandavinsten?
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 6921
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av Marta »

Skulle jag också vilja veta. Märker ingen skillnad, så den gamla koden "bottnade" tydligen inte. Eller så är den nya lika dålig...
gkar
Inlägg: 1453
Blev medlem: 31 oktober 2011, 15:28:29
Ort: Linköping

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av gkar »

Kort kod betyder inte att det går snabbare på en modern processor.

Jag skulle gissa att GCC gör lika snabb eller snabbare kod än inlineassemblern om du ger gcc -Osize och omit frame pointer. Nu vet jag inte hur du får dina variabler, men en bra idé är att tilldela alla dina vaiabler till lokala variabler du aldrig tar adressen på (&kaka tex) eller som inte är invärden eller returväde ur funktionen. Tar du adressen måste variabeln ligga i minnet och omöjliggör registeroptimering.

Det andra du kan göra är att göra loop unrolling. Kompilatorn har lite problem med din kod då den måste förutsätta att masken och p kan överlappa. (pointer aliasing) Det kanske de kan, vad vet jag. Då blir det svårare, om inte.
Kolla att du har ett jämnt antal varv och dela rows och col med 2.

for (y = rows; y > 0; y--) { //rows
for (x = colw; x > 0; x--) { //columns
maskA = *fc_p++; //get pixel from cache
maskB = *fc_p++; //get pixel from cache
tempA = p[0];
tempB = p[1];
tempA &=~maskA; //punch a hole in bkgnd
tempB &=~maskB; //punch a hole in bkgnd
tempA |=maskA & fg;
tempB |=maskB & fg;
p[0])|=tempA; //fill with fg and nxt column
p[1])|=tempB; //fill with fg and nxt column
p+=2;
};
p+=pmx-colw; //nxt row
};

Den koden kommer kompilatorn att gilla bättre. Se också till att du inte har något som är deklarerat 16 bitar brett på x86.

Är det 8 bitars variabler kan du ju utföra allt ovan med 32 eller 64 bitars variabler men kolla då att du har natural alignment. Sedan loopunrollar du det 2 ggr på x86 eller 4 på x64.
Borre
Inlägg: 4570
Blev medlem: 14 juni 2007, 15:43:50
Ort: Hälsingland

Re: LÖST Inline assembleroptimering. Hjälp!

Inlägg av Borre »

Kana du inte posta koden från första inlägget med optimeringar på, så som det föreslås i tidigare inlägg?
Annars är det ju svårt att jämföra och ganska dumt att klaga på första resultatet...
Skriv svar