2016-12-28 2 views
-3

Ich umformuliere diese Frage basierend auf den eingegangenen Kommentaren.Warum läuft C-Programm langsamer, wenn eine Schleife eine Bedingung enthält

Ich habe eine Schleife, die 30 Milliarden Mal läuft und weist einem Speicherbereich, der mit malloc() zugewiesen wurde, Werte zu;

Wenn die Schleife eine Bedingung enthält, läuft sie viel langsamer als wenn die Bedingung nicht vorhanden ist. Überprüfen Sie die folgenden Szenarien:

Ein Szenario: Zustand vorhanden ist, und das Programm ist langsam (43 sec)

Szenario B: Zustand nicht vorhanden ist und das Programm ist viel schneller (4 sec)

// gcc -O3 -c block.c && gcc -o block block.o 



#include <stdio.h> 
#include <stdlib.h> 


#define LEN 3000000000 

int main (int argc, char** argv){ 

    long i,j; 

    unsigned char *n = NULL; 
    unsigned char *m = NULL; 

    m = (unsigned char *) malloc (sizeof(char) * LEN); 

    n = m; 

    srand ((unsigned) time(NULL)); 

    int t = (unsigned) time(NULL); 

    for (j = 0; j < 10; j++){ 

     n = m; 

     for (i = 0; i < LEN; i++){ 


      //////////// A: THIS IS SLOW 
      /* 
      if (i % 2){ 
       *n = 1;   

      } else { 
       *n = 0; 
      } 
      */ 
      /////////// END OF A 


      /////////// B: THIS IS FAST 

      *n = 0; 

      i % 2; 

      *n = 1; 

      /////////// END OF B 

      n += 1; 

     } 
    } 


    printf("Done. %d sec \n", ((unsigned) time(NULL)) - t); 

    free(m); 

    return 0; 
} 

Grüße, KD

+1

Ohne jeden Kontext können wir nur raten. Eine Vermutung ist, dass die 0 als Abschlusszeichen für eine Zeichenfolge verwendet wird, aber wie gesagt, wir brauchen einen Kontext. – Gerhardh

+4

Die Hellseherabteilung ist im Mutterschutz. Alle Fragen zu nicht funktionierendem Code müssen von einem [mcve] begleitet werden. Das Management möchte sich für die entstandenen Unannehmlichkeiten entschuldigen. –

+0

Veröffentlichen Sie einen minimalen vereinfachten Code, den wir ausführen und kompilieren können. Und wenn du recht hast, sage ich viel Abstimmung voraus. –

Antwort

0

Sie können gcc -S -O3 verwenden, um sich den resultierenden Assembler anzusehen. Hier ist ein Beispiel auf einer Intel-Box:

Schnelle Version:

movl %eax, %r12d 
    .p2align 4,,10 
    .p2align 3 
.L2: 
    movl $3000000000, %edx 
    movl $1, %esi 
    movq %rbp, %rdi 
    call memset 
    subq $1, %rbx 
    jne .L2 

Langsam Version:

movl $10, %edi 
    movl %eax, %ebp 
    movl $3000000000, %esi 
    .p2align 4,,10 
    .p2align 3 
.L2: 
    xorl %edx, %edx 
    .p2align 4,,10 
    .p2align 3 
.L5: 
    movq %rdx, %rcx 
    andl $1, %ecx 
    movb %cl, (%rbx,%rdx) 
    addq $1, %rdx 
    cmpq %rsi, %rdx 
    jne  .L5 
    subq $1, %rdi 
    jne  .L2 

Fazit: Der Compiler ist klüger als Sie denken. Es ist in der Lage, die innere Schleife als ein Memset zu optimieren (das ist schneller, weil es SSE/AVX oder REP-Anweisungen auf Intel verwendet). Diese Optimierung kann jedoch nicht eingesetzt werden, wenn die Bedingung beibehalten wird - weil das Ergebnis anders ist.

Verwandte Themen