处理器行为说明

时间:2018-12-04 21:26:22

标签: c optimization cpu

问了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 个答案:

答案 0 :(得分:2)

  

我们应该期望CPU加速吗?

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

您可能会(但不希望如此)认为第一个版本在循环内还有一个额外的乘法运算(额外的3*),因此与该乘法运算可能会产生额外的成本。

您还可以假设(但不期望)编译器可以将两个版本的优化降至一个常量,并且可以生成等效于printf("error %i ******************\n", CONSTANT_CALCULATED_AT_COMPILE_TIME);的代码,而无需任何代码来计算n1或{{1} }。

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