使用-O2减少冒泡排序C程序的时间

时间:2017-08-08 19:10:40

标签: c sorting gcc bubble-sort

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void sort();

int main() {
    int i;
    for (i = 0; i < 100000; i++) {
        sort();
    }
}

void sort() {
    int i, j, k, array[100], l = 99, m;
    for (i = 0; i < 100; i++) {
        array[i] = rand() % 1000 + 1;
    }
    for (k = 0; k < 99; k++) {
        for (j = 0; j < l; j++) {
            if (array[j + 1] > array[j]) {
                int temp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = temp;
            }
        }
        l--;
    }
    for (m = 0; m < 100; m++) {
        printf("%d ", array[m]);
    }
}

在linux shell上,gcc sort -o sort.c然后time ./sort >> out。 如果我执行gcc -o2 sort -o sort.c,类似o3o4,那么时间会继续减少。优化选项如何工作?请根据所有实时,用户时间和系统时间进行解释。

PS:代码可能效率不高。请忽略它。

4 个答案:

答案 0 :(得分:3)

优化选项在读取源代码和将二进制指令写入CPU之间起作用。

GCC是一个多阶段编译器,其阶段大致包括:

  1. 创建&#34;令牌&#34;来自输入文字。
  2. 将这些令牌排列成抽象语法树结构。
  3. 修剪抽象语法树。
  4. 假设有无数个CPU寄存器,创建基于寄存器的指令。
  5. 将寄存器映射到可用的实际寄存器中。
  6. 以加载程序的预期格式写出二进制信息。
  7. 优化可能影响多个位置,通常它们在上述步骤3到5中变得活跃。有许多优化,包括:

    • 常量折叠 - 预先评估常量子表达式。
    • 强度降低 - 用更快的等效物替换慢速操作。
    • 空序列 - 删除无用的操作。
    • 组合操作 - 用一个等效操作替换多个操作。
    • 代数定律 - 使用代数定律来简化或重新排序指令。
    • 特殊情况说明 - 使用针对特殊操作数情况设计的说明。
    • 地址模式操作 - 使用地址模式简化代码。
    • 循环展开 - 用等效指令替换循环
    • 部分循环展开 - 减少循环评估的时间,同时保留整体功能。

    请注意,这些并非所有可能执行的优化,但它开始为您提供一个想法。

    例如,如果编译器看到

    int s = 3;
    while (s < 6) {
       printf("%d\n", s);
       s++;
    }
    

    并且标志设置为展开循环,然后它可能会写出相当于

    的CPU指令
    printf("%d\n", 3);
    printf("%d\n", 4);
    printf("%d\n", 5);
    

    这些指令对我们人类来说可能看起来更加冗长,但CPU命令可能更小,因为不需要查找&#34;现在擦除的s值,也不需要添加一个,或将新更新的值存储回RAM。

    GCC将优化安排到类别中,范围从&#34; safe&#34;风险&#34;。 -O2是速度和安全性之间的良好折衷。更高的-O数字风险更大。

答案 1 :(得分:2)

-O代表optimize,其中gcc将自动采取必要步骤优化您的计划。您可以在此处详细了解GCC为优化您的计划所采取的具体步骤:React-router-dom

但实质上,-O2-O1更优化,-O3优于-O2。这可能在编译的二进制大小方面存在缺陷,其中生成的二进制文件可以使用更多空间,但运行速度更快,反之亦然。您实际上可以将代码粘贴到https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html,并在-O1或下拉列表旁边的任何优化选项中写入以选择编译器,godbolt将显示生成的代码的外观。您将能够看到O1O2之间的差异,即O2生成的代码可能更短,并且会使用大量快捷方式来执行您的算法。

答案 2 :(得分:2)

-O编译器标志控制您希望编译器执行的编译器优化量。简而言之,构建项目需要更长时间,但生成的可执行文件应该更快。有关更多信息,请在命令提示符下键入man gcc,或在gcc -c -Q -O3 --help=optimizers中键入有关为特定标志执行的优化的特定信息。

答案 3 :(得分:1)

gcc提供了许多优化标志。你可以在这里看到每个人具体做的事情:

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

通过增加编译时间,增加内存使用等等,总是需要通过优化进行权衡......

-o2标志启用了许多优化,因此可能无法立即清楚哪些特定的优化会影响排序。您可以单独尝试每个优化,而不是-o2,例如使用-falign-loops标志,以查看是否提供性能提升。