代码之家  ›  专栏  ›  技术社区  ›  Agnius Vasiliauskas

处理器行为解释

  •  -3
  • Agnius Vasiliauskas  · 技术社区  · 6 年前

    询问之后 this question 我很困惑,决定为C编译器程序构建类似的测试。这是我的代码:

    #include <stdio.h>
    #include <time.h>
    #include <math.h>
    #include <stdlib.h>
    
    #define SUMMATIONS 20000000
    
    int main() {
    
        static int speedups[2101] = { 0 };
    
        srand((unsigned)time(NULL));
    
        while (1) {
    
            unsigned int t1, t2, t3, t4;
            signed int tmp, i, n1, n2;
    
            // Slow version
            t1 = clock();
            for (n1 = rand() % 50, i = 0; i < SUMMATIONS; i++) {
                n1 += 3 * i * i;
            }
            t2 = clock();
    
            // Optimized version
            t3 = clock();
            for (n2 = rand() % 50, i = 0; i < SUMMATIONS; i++) {
                n2 += i * i;
            }
            n2 *= 3;
            t4 = clock();
    
            // gather speedup statistics
            if ((int)(t2 - t1) != 0) {
                tmp = (int)(100.0f * ((float)(t2 - t1) - (float)(t4 - t3)) / (float)(t2 - t1));
                tmp = tmp < -100 ? -100 : tmp > 100 ? 100 : tmp;
                tmp = (tmp >= 0 ? 1000 : 2000) + abs(tmp);
                speedups[tmp]++;
            }
    
            // output statistics
            for (i = 0; i < 2101; i++) {
                if (speedups[i] != 0) {
                    char s = i / 1000 == 1 ? '+' : i / 1000 == 2 ? '-' : '?';
                    printf("%c%i : %i\n", s, i % 1000, speedups[i]);
                }
            }
            printf("error %i ******************\n", abs(n2-n1));
    
        }
    
        return 0;
    }
    

    根据GCC编译,带选项 -O3 -march=native

    编辑

    测试代码已更改,因此只有在运行时(而不是编译时)才能知道错误值,所以GCC优化器无法删除循环的代码。

    结果

    当运行时-将CPU命中的计数器重新计算为特定的加速值并输出计数器表。如果我们画出CPU命中与加速值,-我们会 得到这样的图表:

    enter image description here

    所以GCC让程序产生~ 20% 平均加速。

    问题

    我们应该 期待 CPU加速?(根据GCC编译程序预测)

    1 回复  |  直到 6 年前
        1
  •  2
  •   Agnius Vasiliauskas    6 年前

    我们应该期望CPU加速吗?

    不。通过选择使用高级语言,您选择放弃期望与性能相关的任何内容的权利。

    您可以假定(但不期望)第一个版本有一个附加的乘法(附加的 3* )在循环内部,因此可能存在与该乘法相关的额外成本。

    您也可以假定(但不期望)编译器可能会将两个版本优化到一个常量,并可能生成 printf("error %i ******************\n", CONSTANT_CALCULATED_AT_COMPILE_TIME); 无需计算任何代码 n1 n2 在运行时。

    注意,这些随机假设是相互排斥的。