编译器可以优化不相关的命令以使用不同的内核执行吗?

时间:2018-09-20 09:52:15

标签: c++ optimization compiler-optimization

在优化方面,编译器可以更改非相关命令的顺序。 能否也将它们静默优化以在不同的内核中执行?

例如:

...
for (...) 
{
    //...
    int a = a1+a2;
    int b = b1+b2;
    int c = c1+c2;
    int d = d1+d2;
    //...
}
...

是否有可能在优化方面不仅更改执行顺序,而且更改核心数量?编译器在标准上有任何限制吗?

UPD:我不是在问如何并行化代码,而是在问它是否未显式并行化,它是否仍可以由编译器并行化?

2 个答案:

答案 0 :(得分:3)

在这里,不仅有眼神。这些指令(在您的示例中)很可能最终会并行运行,但这不是您所想的。

CPU中有许多级别的硬件并行性,多个内核只是最高的 1)。在CPU内核内部,您具有其他级别的硬件并行化,大多数情况下都是透明的 2)(您不通过软件对其进行控制,并且实际上看不到它们,有时可能只是它们的副作用) 。其中包括管道,额外的总线通道,每个核心有多个ALU(算术逻辑单元)和FPU(浮点单元)。

您的指令的不同阶段将在管道中并行运行(现代x86处理器具有十几个管道阶段),并且可能不同的指令将在不同的ALUS中并行运行(现代x86 CPU每个内核具有大约5个ALU)。

所有这些事情都是在编译器不执行任何操作的情况下发生的(sup> 2)。而且它是免费的(考虑到硬件,并非免费在硬件中添加此功能)。在不同内核中执行指令不是免费的。创建不同的线程成本很高。将数据移动到其他内核可用是昂贵的。等待其他内核执行的同步开销很大。创建和同步线程有很多开销。对于这样的小指令,这是不值得的。从多线程中真正受益的情况将涉及到一种分析,该分析如今过于复杂,因此实际上不可行。将来有一天,编译器将能够确定您的串行算法实际上是一种排序算法,并且可以有效,正确地对其进行并行化。在此之前,我们必须依靠语言支持,库支持和/或开发人员支持来并行化算法。

1)好,实际上是超线程。

2)由MSalters指出:

  

现代的编译器非常了解各种ALU,并且会做   努力从中受益。特别是,寄存器分配是   经过优化,因此您无需ALU争夺同一寄存器,   从抽象顺序可能看不到的东西   模型。

所有这些都间接影响了执行,从而使硬件体系结构受益,没有明确的指令或声明。

答案 1 :(得分:0)

是的,只要生成的可观察行为与代码应具有的可观察行为相匹配,则编译器可以按任何顺序执行操作(包括根本不执行操作)。汇编指令,运行时,线程数等是不可观察的行为。

我还要补充一点,如果没有程序员的明确指示,编译器不太可能决定这样做。即使标准允许,编译器也可以帮助程序员,并且在许多情况下随机启动额外的线程是意外的