2016-03-30 68 views
3

我挣扎理解为什么这个代码与英特尔编译器12起泡的速度运行,而真正与英特尔编译器16英特尔compilator for循环速度C

#include <stdlib.h> 
#include <time.h> 
int main(int argc, char *argv[]) 
{ 
    int i,t; 
    int n=10000000; 
    int T=1000; 
    time_t t1,t2; 

    // double A[n],B[n],C[n]; 
    double *A = (double*) malloc (sizeof(double)*n); 
    double *B = (double*) malloc (sizeof(double)*n); 
    double *C = (double*) malloc (sizeof(double)*n); 



    for (i=0;i<n;i++) 
    { 
     A[i]=1.0; 
     B[i]=2.0; 
    } 
    t1=clock(); 

    for (t=0;t<T;t++) 
     for (i=0;i<n;i++) 
      C[i]=A[i]*B[i]; 

    t2=clock(); 
    double sum=0.0; 
    for (i=0;i<n;i++) sum += C[i]; 
    printf("sum %f\n",sum); 
    printf("time %f\n",(double)(t2-t1)/CLOCKS_PER_SEC); 
} 

  • 英特尔编译器12减慢:在沙质桥上跑0.1秒;英特尔 编译器16:取25秒在沙质桥运行

生成文件: ICC -O2 -o阵列array.c

+1

不相关:不要在C中投放'malloc'和好友的结果! – Olaf

+0

也许会使'double's'volatile'? –

+2

您是否尝试过使用'-O3'而不是'-O2'? –

回答

5

可能的是,编译器中的一个积极优化去掉一个繁重的嵌套循环。看起来您的优化代码似乎很可能实际上结束为:

t1=clock(); 
t2=clock(); 
double sum=0.0; 
for (i=0;i<n;i++) sum += A[i]*B[i]; 

编译器完成此类优化是非常好的。您可以通过使循环迭代器volatile来阻止优化。

确保您在两个编译器上启用了相同级别的优化。

+3

没有提到事实'A'和'B'是所有'[i]'的常量......循环可以完全消失。 –

+1

@EugeneSh。是的,这是一个简单的例子。真正的程序会有更多的优化,尤其是在'-O3'。 – Lundin

+0

是的。这一定是它。添加volatile会使其运行相同,并与所有编译器一起编译 –

2

这两个嵌套循环是vectorisable,只要编译器确定ABC所指向的三个内存区域不是别名。具体而言,通过C存储的值永远不能通过AB重新读取 - 如果循环的迭代并行运行,并且载入和存储顺序不同于代码中的暗示顺序,则这将是一种危险。

在一般情况下,编译器将不能从函数调用返回的指针中推断出它,尽管它可以合法地知道更多关于标准库函数的语义,比如函数签名的malloc()独自会推断。

您看到的差异可能是由于编译器版本之间的别名规则的严格性 - 或者可能来自不同的默认选项开关而引起的。

restrict限定符添加到指针声明中会告诉编译器,它可以假定通过使用指针不会发生别名,并且负责保证这一点。

double * restrict A = malloc (sizeof(double)*n); 
double * restrict B = malloc (sizeof(double)*n); 
double * restrict C = malloc (sizeof(double)*n);