首页 文章

重用变量对于指令级并行和OoO执行是否有害?

提问于
浏览
1

我正在研究处理器,引起我注意的一件事是高性能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 回答

  • 1

    现代微处理器是一种非常复杂的设备,并且已经具有足够的复杂性,因此了解其功能的每个方面都是大多数人无法企及的 . 您的编译器或运行时引入了一个额外的层,这增加了复杂性 . 这里的通用性真的很可能,因为ARM处理器X可能会处理这个问题,而不是ARM处理器Y,这两者都不同于Intel U或AMD V.

    仔细查看您的代码:

    int myResult;
    
    myResult = myFunc1(); // 1
    myResult = myFunc2(); // 2
    j = myResult + 3;     // 3
    

    int myResult 行只是指示编译器会有一个名为 myResult 的类型为 int 的变量 . 它's not initialized, so there' s还没有必要做任何事情 .

    在第一次分配时,不使用该值 . 默认情况下,编译器通常会将代码直接转换为机器指令,但是当您启用通常用于 生产环境 代码的优化时,该假设就会消失 . 一个好的编译器会认识到这个值永远不会被使用,并且会省略赋值 . 更好的编译器会警告您该值永远不会被使用 .

    第二个实际上分配给变量,后来使用该变量 . 显然,在第三次任务发生之前,必须完成第二项任务 . 那些函数的作用是什么 .

    一个“超标量”处理器,或者能够无序运行的处理器,对于它可以获得多大的野心有限制 . 它最适合的代码类型类似于以下内容:

    int a = 1;
    int b = f();
    int c = a * 2;
    int d = a + 2;
    
    int e = g(b);
    

    a 的分配是直截了当的 . b 是计算值 . 令人感兴趣的地方是 cd 具有相同的依赖关系,并且实际上可以并行执行 . 它们也不依赖于 b 所以理论上它们可以在 f() 调用之前,期间或之后运行,只要结束状态是正确的 .

    单个线程可以同时执行多个操作,但是大多数处理器对它们的类型和数量有限制 . 例如,可能发生浮点乘法和整数加,或两个整数加,但不是两个浮点乘法运算 . 它取决于CPU具有哪些操作,可以操作哪些寄存器,以及编译器如何提前排列数据 .

    如果您正在寻找优化代码并减少纳秒数,那么您需要在目标CPU上找到一本非常好的技术手册,并花费数小时尝试不同的方法和基准测试 .

    简短的回答是变量并不重要 . 这完全取决于依赖项,编译器以及CPU的功能 .

相关问题