首页 > 解决方案 > 编译器可以优化不相关的命令以使用不同的内核执行吗?

问题描述

编译器可以在优化方面改变非相关命令的顺序。它还可以静默优化它们以在不同的内核中执行吗?

例如:

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

是否会发生在优化方面不仅可以更改执行顺序,还可以更改内核数量?编译器在标准上有什么限制吗?

UPD:我不是在问如何并行化代码,我是在问它是否没有明确地并行化,它仍然可以被编译器并行化吗?

标签: c++optimizationcompiler-optimization

解决方案


这里有更多的东西。很可能指令(在您的示例中)最终会并行运行,但这不是您的想法。

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

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

所有这一切都发生在编译器没有做任何事情的情况下2). 而且它是免费的(鉴于硬件,在硬件中添加此功能不是免费的)。在不同的内核中执行指令不是免费的。创建不同的线程是昂贵的。将数据移动到其他内核可用的成本很高。等待其他内核执行的同步成本很高。创建和同步线程有很多开销。像这样的小指令是不值得的。并且从多线程中真正受益的案例将涉及今天过于复杂的分析,因此实际上不可行。在未来的某一天,编译器将能够识别您的串行算法实际上是一种排序,并有效且正确地将其并行化。在那之前,我们必须依靠语言支持,

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

2)正如MSalters所指出的:

现代编译器非常了解各种 ALU,并将努力从中受益。特别是,寄存器分配经过优化,因此您不会让 ALU 竞争相同的寄存器,这在抽象顺序模型中可能并不明显。

所有这一切都间接影响执行以使硬件架构受益,没有明确的指令或声明。


推荐阅读