哪个运算符在<<<<和*循环?

时间:2016-01-28 08:04:37

标签: c++ c

我正在学习c / c ++代码优化。编写一个简单的for循环程序,for循环的哪一部分将比其他w.r.t<<和*运算符。下面的代码片段。

x

3 个答案:

答案 0 :(得分:3)

首先,这是使用乘法运算符的程序集(我添加了注释):

.LC0:
        .string " "
main:
        pushq   %rbp
        movl    $10, %ebp          // Part of loop
        pushq   %rbx
        movl    $1, %ebx           // Part of loop
        subq    $8, %rsp
.L2:
        movl    %ebx, %esi
        movl    std::cout, %edi
        addl    %ebx, %ebx         // Part of loop
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
        movl    $1, %edx
        movl    $.LC0, %esi
        movq    %rax, %rdi
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        subl    $1, %ebp           // Part of loop
        jne     .L2                // Part of loop
        addq    $8, %rsp 
        xorl    %eax, %eax
        popq    %rbx
        popq    %rbp
        ret
        subq    $8, %rsp
        movl    std::__ioinit, %edi
        call    std::ios_base::Init::Init()
        movl    $__dso_handle, %edx
        movl    std::__ioinit, %esi
        movl    std::ios_base::Init::~Init(), %edi
        addq    $8, %rsp
        jmp     __cxa_atexit

这是使用移位运算符的程序集:

.LC0:
        .string " "
main:
        pushq   %rbp
        movl    $10, %ebp
        pushq   %rbx
        movl    $1, %ebx
        subq    $8, %rsp
.L2:
        movl    %ebx, %esi
        movl    std::cout, %edi
        addl    %ebx, %ebx
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
        movl    $1, %edx
        movl    $.LC0, %esi
        movq    %rax, %rdi
        call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
        subl    $1, %ebp
        jne     .L2
        addq    $8, %rsp
        xorl    %eax, %eax
        popq    %rbx
        popq    %rbp
        ret
        subq    $8, %rsp
        movl    std::__ioinit, %edi
        call    std::ios_base::Init::Init()
        movl    $__dso_handle, %edx
        movl    std::__ioinit, %esi
        movl    std::ios_base::Init::~Init(), %edi
        addq    $8, %rsp
        jmp     __cxa_atexit

完全相同(我只使用-O3使用GCC 5.3 for x86编译,因此其他编译器和其他体系结构可能不是这样。)

在查看Chris评论中发布的链接后,自动突出显示似乎移位操作员需要其他说明:

subl    $1, %ebp
jne     .L2
movl    $10, %ebp    // Actually not part of loop
movl    $1, %ebx     // Actually not part of loop

与乘法相比,即:

subl    $1, %ebp
jne     .L3

这与我发布的原始程序集不同(因为两者完全相同)。

如Revolver_Ocelot的评论中所述,说明

movl    $10, %ebp    
movl    $1, %ebx     

只是为下一个循环设置计数器,因此循环组件实际编译为相同的程序集(对于此编译器和体系结构),如单独的比较所示。

更新:根据Flikk的评论说会议将有所不同,这里是unoptimised version,表明它们是相同的。

答案 1 :(得分:1)

您正在尝试微观优化。当我开始说这是初学者节省微秒,真正的程序员节省了几毫秒。如今初学者可以节省纳秒,真正的程序员可以节省微秒: - )

您正在输出我到std :: cout。那时,我如何计算所以完全不相关,因为输出需要几千倍的时间。

现在让我们来看看程序的功能。在某些时候,您会遇到溢出,这会给您未定义的行为,这意味着任何都可能发生。正确的程序比快速程序重要数千倍。因此,当您的代码已经破坏时,任何优化尝试都是毫无意义的。

现在让我们来看看你在做什么。问问自己:编译器是否弄清楚你在做什么?编译器显然会看到每个变量将i乘以2.编译器将使用以最快的方式将i乘以2 ,无论方法是什么。可能会把我添加到自己:-)所以你正在做的事情再次毫无意义;编译器比这更聪明。

回到微观优化:它们完全无效,因为编译器在微优化方面比你好十倍。真正的程序员不会试图让操作变得更快;他们开发的数据结构和算法开始时需要的操作少得多!他们首先测量以找出需要时间的内容并优化其计数的位置,而不是尝试优化随机位。然后他们会测量是否有任何优化尝试确实有效。

答案 2 :(得分:0)

我可以给你一个简单的想法,它可以帮助你判断i * = 2和i = i&lt;&lt; 1之间哪个更快。

更新MAX = 10 18 并使用long long int作为数据类型。现在使用time()函数独立测量两个for循环的运行时间。并找出运行时间的差异。

注意:由于最多会有60次迭代,因此运行时间的差异可能无法比较,因此在这种情况下您可以使用BigInteger库。

结果:位操作更快。