【问题标题】:Intel C++ optimizer removes masm code英特尔 C++ 优化器删除了 masm 代码
【发布时间】:2014-10-13 16:06:17
【问题描述】:

我最近开始在我的一些项目中使用英特尔 C++ 编译器,同时还学习了 masm 汇编。我不断听到为什么不值得学习汇编,因为编译器在优化代码方面做得很好,所以想一劳永逸地看看哪个更快。为了尝试这样做,我有以下 c++ 代码:

#include <iostream>
#include <time.h>

using namespace std;

extern "C" {
int Add(int a, int b);
}


int main(int argc, char * argv[]){
        int startingTime = clock();
        for (int i = 0; i < 100; i++)
        {
            cout << "normal: " << i << endl;
            cout << 1000 + 1000 << endl;
        }
        int timeTaken1 = clock() - startingTime;

        startingTime = clock();
        for (int i = 0; i < 100; i++){
             cout << "assem" << i << endl;
             cout << Add(2000, 2000) << endl;
        }
        int timeTaken2 = clock() - startingTime;

        cout << "Time taken under normal addition: " << timeTaken1 << endl;
        cout << "Time taken under assembly addition: " << timeTaken2 << endl;

        cin.get();
        return 0;
   }

还有下面的masm代码:

.model flat
.386

.code

    public _Add

_Add PROC
        push ebp            ;
        mov ebp, esp        ;
        mov eax, [ebp + 8]  ;
        mov ebx, [ebp + 12] ;
        add eax, ebx        ;
        leave               ; cleanup
        ret                 ;


_Add endp
end

我正在使用 Visual Studio 编译它,使用 Intel Composer 插件。当我在 Debug 模式下运行它时,它运行良好——我可以看到“normal 99”和“assem 99”以及相关的数字。当我使用为编译器指定的 /0d 运行它时,它也可以正常工作。但是,当指定 /02、/0x 或 /03 时,它只显示正常的 (i+j) 加法循环和汇编程序加法的第一个值,即只显示汇编 0 和 4000。

我的猜测是英特尔编译器正在优化汇编代码(这适用于 VC++ 编译器),我很想知道为什么会发生这种情况以及如何解决它,同时仍然让英特尔优化C++部分。

谢谢 蜘蛛网

编辑: 我知道这是迟到了,但感谢所有的答复。似乎是汇编代码中的错误,而不是intel编译器没有使用汇编代码。

【问题讨论】:

  • 微基准测试很棘手。如果我没看错,您正试图在 C++ 与 asm 中对 int-addition 进行基准测试,结果一败涂地。仅供参考:C++ 代码不会做任何添加,这是优化的,甚至可能已经在 -O0 处。不知道如何以及是否会优化 asm。
  • 你不应该告诉编译器你正在改变eaxebx吗?很可能,优化后的代码使用其中之一来存储i
  • 顺便说一下,正如@Deduplicator 已经说过的那样:1000 + 1000 是“优化”(在这种情况下是常量折叠)的明确候选者,它很可能永远不会 出现在生成的代码中。警告 #2:即使您将这些替换为变量,本机编译器也很可能会将它们保存在寄存器中并添加它们,而您自己的汇编程序函数始终必须首先加载它们。
  • 执行任何 IO,例如写入标准输出,将完全掩盖此类计算所花费的时间长度。此外,从内存中检索和添加变量的值可能需要大约 10 个周期(几纳秒),而时钟的分辨率可能要长 1000 到 1000000 倍。
  • 事实上,对于大多数日常目的,您不应该工作在汇编中,是否意味着它不是'值得学习。我认为学习它会让任何人成为更好的程序员,因为它让你最接近机器真正“思考”的方式。然后,即使您使用高级语言工作,您也可以应用这些知识。

标签: c++ c masm icc intel-composer


【解决方案1】:

您的汇编代码正在破坏EBX 寄存器(如 Jongware 所述),这可能是您的 C++ 代码中的第二个循环仅执行一次的原因。如果i 存储在EBX 中,那么将Add 中的EBX 更改为2000 将导致循环条件i &lt; 100 的下一次测试失败。

您需要在汇编代码中保存和恢复EBX 寄存器,或者您需要选择另一个不会在函数调用中保留的寄存器(EAXEDXECX) .

【讨论】:

  • 不需要ebx 寄存器! add 可以使用内存操作数。
猜你喜欢
  • 2018-08-03
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
  • 2011-02-14
  • 1970-01-01
  • 2011-12-15
  • 2011-04-06
  • 1970-01-01
相关资源
最近更新 更多