2016-12-28 107 views
-3

我正在根据收到的意见重新编写此问题。我有一个循环,运行300亿次,并为使用malloc()分配的内存块分配值;为什么C程序在循环包含条件时运行速度更慢

当循环包含一个条件时,它会比条件不存在时慢得多。查看以下情形:

情形A:条件存在且程序是缓慢(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来看看生成的汇编程序。 这里是在英特尔盒的例子:

快速版本:

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(因为它在Intel上使用SSE/AVX或REP指令,所以速度更快)。但是,如果条件保持不变,则此优化无法启动 - 因为结果不同。

相关问题