我正在研究处理器,引起我注意的一件事是高性能CPU能够execute more than one instruction during a clock cycle甚至execute them out of order以提高性能 . 所有这些都没有编译器的任何帮助 .
据我所知,处理器能够通过分析_722124来确定哪些指令可以先运行/在同一个ILP-paralell-step(问题)中运行 .
@edit
我会试着举个例子 . 想象一下这两段代码:
int myResult;
myResult = myFunc1(); // 1
myResult = myFunc2(); // 2
j = myResult + 3; // 3
int myFirstResult, mySecondResult;
myFirstResult = myFunc1(); // 1
mySecondResult = myFunc2(); // 2
j = mySecondResult + 3; // 3
他们都做同样的事情,区别在于,第一次我重用我的变量而在第二次我没有 .
我假设(如果我错了请纠正我)处理器可以在第二个例子的指令1之前运行指令2和3,因为数据将存储在两个不同的位置(寄存器?) .
对于第一个示例,这是不可能的,因为如果它在指令1之前运行指令2和3,则指令1上分配的值将保留在存储器中(而不是指令2中的值) .
Question is :
如果我重用变量(如第一个例子中),是否有任何策略在1之前运行指令2和3?
或者重用变量会阻止指令级并行和OoO执行?
1 回答
现代微处理器是一种非常复杂的设备,并且已经具有足够的复杂性,因此了解其功能的每个方面都是大多数人无法企及的 . 您的编译器或运行时引入了一个额外的层,这增加了复杂性 . 这里的通用性真的很可能,因为ARM处理器X可能会处理这个问题,而不是ARM处理器Y,这两者都不同于Intel U或AMD V.
仔细查看您的代码:
int myResult
行只是指示编译器会有一个名为myResult
的类型为int
的变量 . 它's not initialized, so there' s还没有必要做任何事情 .在第一次分配时,不使用该值 . 默认情况下,编译器通常会将代码直接转换为机器指令,但是当您启用通常用于 生产环境 代码的优化时,该假设就会消失 . 一个好的编译器会认识到这个值永远不会被使用,并且会省略赋值 . 更好的编译器会警告您该值永远不会被使用 .
第二个实际上分配给变量,后来使用该变量 . 显然,在第三次任务发生之前,必须完成第二项任务 . 那些函数的作用是什么 .
一个“超标量”处理器,或者能够无序运行的处理器,对于它可以获得多大的野心有限制 . 它最适合的代码类型类似于以下内容:
a
的分配是直截了当的 .b
是计算值 . 令人感兴趣的地方是c
和d
具有相同的依赖关系,并且实际上可以并行执行 . 它们也不依赖于b
所以理论上它们可以在f()
调用之前,期间或之后运行,只要结束状态是正确的 .单个线程可以同时执行多个操作,但是大多数处理器对它们的类型和数量有限制 . 例如,可能发生浮点乘法和整数加,或两个整数加,但不是两个浮点乘法运算 . 它取决于CPU具有哪些操作,可以操作哪些寄存器,以及编译器如何提前排列数据 .
如果您正在寻找优化代码并减少纳秒数,那么您需要在目标CPU上找到一本非常好的技术手册,并花费数小时尝试不同的方法和基准测试 .
简短的回答是变量并不重要 . 这完全取决于依赖项,编译器以及CPU的功能 .