2016-12-28 1 views
-3

Я перефразирую этот вопрос на основе полученных комментариев.Почему программа C работает медленнее, когда цикл содержит условие

У меня есть цикл, который работает 30 миллиардов раз и присваивает значения блоку памяти, назначенному с помощью malloc();

Когда цикл содержит условие, он работает намного медленнее, чем когда условие отсутствует. Обзор сценариев ниже:

Сценарий: Условие присутствует и программу медленно (43 сек)

Сценария B: Состояние нет и программы намного быстрее (4 сек)

// 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; 
} 

С уважением, KD

+1

Без какого-либо контекста мы можем только догадываться. Предполагается, что 0 используется как символ окончания для некоторой строки, но, как сказано, нам нужен какой-то контекст. – Gerhardh

+4

Отделение ясновидения находится в декретном отпуске. Все вопросы о неработающем коде должны сопровождаться [mcve]. Руководство желает извиниться за любые неудобства. –

+0

Опубликуйте минимальный упрощенный код, который мы можем запускать и компилировать. И если вы правы, я предсказываю большое голосование. –

ответ

0

Вы можете использовать gcc -S-O3, чтобы посмотреть на полученный ассемблер. Вот пример на коробке Intel:

Быстрая версия:

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 

Медленная версия:

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 

Вывод: компилятор умнее, чем вы думаете. Он способен оптимизировать внутренний цикл как memset (что быстрее, потому что использует инструкции SSE/AVX или REP на Intel). Однако эта оптимизация не может срабатывать, если условие сохраняется, потому что результат отличается.

Смежные вопросы