簡體   English   中英

為什么gcc的輸出比Visual Studio的輸出慢得多(對於此代碼)?

[英]Why gcc's output much slower than Visual Studio's (for this code)?

當我使用gcc通過定期更新的Ubuntu 16.04 64bit編譯以下代碼時

gcc source.c -O3 --fast-math

可執行文件大約需要45秒的CPU時間才能運行。 但是,在同一台計算機上以及在Windows 7 64位版本中,在發布模式下使用Visual Studio 2012,運行CPU時間不到10秒。 造成這種差異的主要原因是什么? 我沒有使用足夠的gcc優化選項嗎? Visual Studio的編譯器更好嗎? 或者是其他東西?

#include <stdio.h>
#include <math.h>
#include <time.h>

#define Nx 1000

int main()
{
    double d = 0.015e-2;        // meter
    double V0 = 400;            // volt
    double De = 1800e-4;        // m^2 per sec
    double mu_e = 2.9e1 / 760;  // m^2 per volt sec
    double n0 = 1e19;           // per m^3
    double e_eps = 1.602e-19 / 8.854e-12;
    double ne[Nx], je[Nx], E[Nx];
    double dx = d / (Nx - 1);
    double dt = 1e-14;          // s
    const int Nt = 500000;
    int i, k;
    double sum;
    FILE *fp_ne, *fp_E;
    double alpha, exp_alpha, R;
    int ESign = -1;
    clock_t start_t, end_t;

    start_t = clock();
    // initialization
    for (i = 1; i < Nx; i++)
        ne[i] = n0;
    ne[0] = 1e-4 * n0;

    for (i = 0; i < Nx; i++)
        E[i] = -V0 / d;

    // time loop
    for (k = 0; k < Nt; k++)
    {
        if (k%1000==0) printf("k = %d\n", k);
        for (i = 0; i < (Nx-1); i++)
        {
            alpha = mu_e*dx*E[i]/De;
            exp_alpha = exp(alpha);
            R = (exp_alpha-1)/alpha;
            je[i] = (De/(dx*R))*(ne[i]-exp_alpha*ne[i+1]);
        }

        for (i = 1; i < (Nx - 1); i++)
            ne[i] += -dt/dx*(je[i] - je[i-1]);
        ne[Nx - 1] = ne[Nx - 2];

        sum = 0;
        for (i = 0; i < (Nx - 1); i++)
            sum += dx*je[i];
        for (i = 0; i < (Nx - 1); i++)
        {
            E[i] += -dt*e_eps*(sum / d - je[i]);
            if (E[i]>=0) ESign=+1;
        }
        if (ESign==1) break;
    }

    // output
    printf("time=%e\n",k*dt);
    fp_ne = fopen("ne.txt", "w");
    fp_E = fopen("E.txt", "w");
    fprintf(fp_ne, "# x (cm)\tne(per cm^3)\n");
    fprintf(fp_E,  "# x (cm)\tE(V/cm)\n");
    for (i = 0; i < Nx; i++)
        fprintf(fp_ne, "%f\t%e\n", i*dx*100,ne[i]/1e6);
    for (i = 0; i < Nx-1; i++)
        fprintf(fp_E, "%f\t%e\n", i*dx*100, fabs(E[i])/1e2);
    fclose(fp_ne);
    fclose(fp_E);
    end_t = clock();
    printf("CPU time = %f\n", (double)(end_t - start_t) / CLOCKS_PER_SEC);
}

我要做的第一件事是注釋掉循環中的I / O。

//if (k%1000==0) printf("k = %d\n", k);

僅通過該更改,我獲得了以下計時。 最后的fprintf調用確實會顯着影響時序,但不會影響它們的相對差異,因此,我不再贅述所有這些時序。

我在Arch Linux第一代Core i5上獲得了這些計時信息(全部使用標准-O2編譯):

  • GCC 7.1:

     CPU time = 23.459520 
  • 鐺4.0.1:

     CPU time = 22.936315 
  • 英特爾17.0.4:

     CPU time = 7.830828 

在同一台計算機上Windows 10的Qemu / libvirt虛擬機上,我得到以下計時:

  • MinGW-w64 GCC 6.3:

     CPU time = 76.122000 
  • VS 2015.3:

     CPU time = 13.497000 
  • VS 2017:

     CPU time = 49.306000 

在WINE上(本機Linux,但有Win32 API仿真,仍應與本機Linux代碼執行相當)

  • MinGW-w64 GCC 6.3:

     CPU time = 56.074000 
  • VS 2015.3:

     CPU time = 12.048000 
  • VS 2017:

     CPU time = 34.541000 

長話短說:看來這些輸出針對此特定問題的最佳代碼:

  1. 英特爾在Linux上(可能也在Windows上)
  2. VS 2015.3
  3. Linux上的GCC / Clang
  4. VS 2017
  5. MinGW-w64 GCC。

查看裝配體將是深入了解此問題的唯一方法,但正確地進行分析超出了我的范圍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM