c++ - 优化 : Inline or Macrofunction?

标签 c++ arrays optimization

我需要尽可能优化程序。现在我遇到了这个问题:我有一个一维数组,它以像素数据的形式表示纹理。我现在需要处理这些数据。通过以下函数访问该数组:

(y * width) + x

具有 x,y 坐标。现在的问题是,这个功能最优化的方式是什么,我考虑了以下两种可能:

内联:

inline int Coords(x,y) { return (y * width) + x); }

宏:

#define COORDS(X,Y) ((Y)*width)+(X)

哪一个是这里使用的最佳实践,或者有没有办法获得我不知道的更优化的变体?

最佳答案

我编写了一个小测试程序来查看这两种方法之间的区别。

这里是:

#include <cstdint>
#include <algorithm>
#include <iterator>
#include <iostream>

using namespace std;

static constexpr int width = 100;

inline int Coords(int x, int y) { return (y * width) + x; }
#define COORDS(X,Y) ((Y)*width)+(X)

void fill1(uint8_t* bytes, int height)
{
    for (int x = 0 ; x < width ; ++x) {
        for (int y = 0 ; y < height ; ++y) {
            bytes[Coords(x,y)] = 0;
        }
    }
}

void fill2(uint8_t* bytes, int height)
{
    for (int x = 0 ; x < width ; ++x) {
        for (int y = 0 ; y < height ; ++y) {
            bytes[COORDS(x,y)] = 0;
        }
    }
}

auto main() -> int
{
    uint8_t buf1[100 * 100];
    uint8_t buf2[100 * 100];

    fill1(buf1, 100);
    fill2(buf2, 100);

    // these are here to prevent the compiler from optimising away all the above code.
    copy(begin(buf1), end(buf1), ostream_iterator<char>(cout));
    copy(begin(buf2), end(buf2), ostream_iterator<char>(cout));

    return 0;
}

我是这样编译的:

c++ -S -o intent.s -std=c++1y -O3 intent.cpp

然后查看源代码,看看编译器会做什么。

正如预期的那样,编译器完全忽略了程序员的所有优化尝试,而是只查看表达的意图、副作用和别名的可能性。然后它为两个函数发出完全相同的代码(当然是内联的)。

程序集的相关部分:

    .globl  _main
    .align  4, 0x90
_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq   %rbp
Ltmp16:
    .cfi_def_cfa_offset 16
Ltmp17:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp18:
    .cfi_def_cfa_register %rbp
    pushq   %r15
    pushq   %r14
    pushq   %r13
    pushq   %r12
    pushq   %rbx
    subq    $20024, %rsp            ## imm = 0x4E38
Ltmp19:
    .cfi_offset %rbx, -56
Ltmp20:
    .cfi_offset %r12, -48
Ltmp21:
    .cfi_offset %r13, -40
Ltmp22:
    .cfi_offset %r14, -32
Ltmp23:
    .cfi_offset %r15, -24
    movq    ___stack_chk_guard@GOTPCREL(%rip), %r15
    movq    (%r15), %r15
    movq    %r15, -48(%rbp)
    xorl    %eax, %eax
    xorl    %ecx, %ecx
    .align  4, 0x90
LBB2_1:                                 ## %.lr.ph.us.i
                                        ## =>This Loop Header: Depth=1
                                        ##     Child Loop BB2_2 Depth 2
    leaq    -10048(%rbp,%rcx), %rdx
    movl    $400, %esi              ## imm = 0x190
    .align  4, 0x90
LBB2_2:                                 ##   Parent Loop BB2_1 Depth=1
                                        ## =>  This Inner Loop Header: Depth=2
    movb    $0, -400(%rdx,%rsi)
    movb    $0, -300(%rdx,%rsi)
    movb    $0, -200(%rdx,%rsi)
    movb    $0, -100(%rdx,%rsi)
    movb    $0, (%rdx,%rsi)
    addq    $500, %rsi              ## imm = 0x1F4
    cmpq    $10400, %rsi            ## imm = 0x28A0
    jne LBB2_2
## BB#3:                                ##   in Loop: Header=BB2_1 Depth=1
    incq    %rcx
    cmpq    $100, %rcx
    jne LBB2_1
## BB#4:
    xorl    %r13d, %r13d
    .align  4, 0x90
LBB2_5:                                 ## %.lr.ph.us.i10
                                        ## =>This Loop Header: Depth=1
                                        ##     Child Loop BB2_6 Depth 2
    leaq    -20048(%rbp,%rax), %rcx
    movl    $400, %edx              ## imm = 0x190
    .align  4, 0x90
LBB2_6:                                 ##   Parent Loop BB2_5 Depth=1
                                        ## =>  This Inner Loop Header: Depth=2
    movb    $0, -400(%rcx,%rdx)
    movb    $0, -300(%rcx,%rdx)
    movb    $0, -200(%rcx,%rdx)
    movb    $0, -100(%rcx,%rdx)
    movb    $0, (%rcx,%rdx)
    addq    $500, %rdx              ## imm = 0x1F4
    cmpq    $10400, %rdx            ## imm = 0x28A0
    jne LBB2_6
## BB#7:                                ##   in Loop: Header=BB2_5 Depth=1
    incq    %rax
    cmpq    $100, %rax
    jne LBB2_5
## BB#8:
    movq    __ZNSt3__14coutE@GOTPCREL(%rip), %r14
    leaq    -20049(%rbp), %r12
    xorl    %ebx, %ebx
    .align  4, 0x90
LBB2_9:                                 ## %_ZNSt3__116ostream_iteratorIccNS_11char_traitsIcEEEaSERKc.exit.us.i.i13
                                        ## =>This Inner Loop Header: Depth=1
    movb    -10048(%rbp,%r13), %al
    movb    %al, -20049(%rbp)
    movl    $1, %edx
    movq    %r14, %rdi
    movq    %r12, %rsi
    callq   __ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m
    incq    %r13
    cmpq    $10000, %r13            ## imm = 0x2710
    jne LBB2_9
## BB#10:
    movq    __ZNSt3__14coutE@GOTPCREL(%rip), %r14
    leaq    -20049(%rbp), %r12
    .align  4, 0x90
LBB2_11:                                ## %_ZNSt3__116ostream_iteratorIccNS_11char_traitsIcEEEaSERKc.exit.us.i.i
                                        ## =>This Inner Loop Header: Depth=1
    movb    -20048(%rbp,%rbx), %al
    movb    %al, -20049(%rbp)
    movl    $1, %edx
    movq    %r14, %rdi
    movq    %r12, %rsi
    callq   __ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m
    incq    %rbx
    cmpq    $10000, %rbx            ## imm = 0x2710
    jne LBB2_11
## BB#12:                               ## %_ZNSt3__14copyIPhNS_16ostream_iteratorIccNS_11char_traitsIcEEEEEET0_T_S7_S6_.exit
    cmpq    -48(%rbp), %r15
    jne LBB2_14
## BB#13:                               ## %_ZNSt3__14copyIPhNS_16ostream_iteratorIccNS_11char_traitsIcEEEEEET0_T_S7_S6_.exit
    xorl    %eax, %eax
    addq    $20024, %rsp            ## imm = 0x4E38
    popq    %rbx
    popq    %r12
    popq    %r13
    popq    %r14
    popq    %r15
    popq    %rbp
    retq

请注意,如果没有对 copy(..., ostream_iterator...) 的两次调用,编译器会推测该程序的总效果为零,并拒绝发出任何代码,除了从 main() 返回 0

故事的寓意:停止尝试做编译器的工作。继续你的。

您的工作是尽可能优雅地表达意图。就这样。

关于c++ - 优化 : Inline or Macrofunction?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33627765/

相关文章:

C++实例化模板模板类

arrays - 在 Swift 中使用过滤器时如何处理元素位置

arrays - Matlab:将矩阵 reshape 为一维数组,并将重叠元素加在一起

swift - 是否可以使用动态属性来保存跨兄弟类的重复排序代码?

c++ - SDL2 渲染器给我带来了问题

c++ - 输入第一个数组出了什么问题?

c++ - 可以使用ofstream在打印机上打印

javascript - 对动态填充的对象数组进行排序

asp.net - 有哪些方法可以优化 ASP.NET 缓存的使用?

MySQL 5.1 在存在索引时使用文件排序事件