Debug быстрее Release - почему?

Проблема следующего характера - писал программу для университета, но получился очень интересный результат. При выполнении следующего простого кода конфигурация Debug оказывается быстрее Release, а эмулируемая архитектура x86_64 оказывается быстрее родной arm64

Характеристика системы: MacBook M4, 12 ядер, 24 гб оперативной памяти

Собирал в CLion, пробовал на разных компиляторах, результат один и тот же

CMake Options:

DebugX86: -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_BUILD_TYPE=Debug
ReleaseX86: -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_BUILD_TYPE=Release
DebugARM: -DCMAKE_BUILD_TYPE=Debug
ReleaseARM: -DCMAKE_BUILD_TYPE=Release

Код:

// Параметры
long long counter;
int val = 1;
#define NUMBER 10000000001ll

void fun1(int a, long long start, long long stop, long long *pcounter) {
    volatile long long count = 0; // volatile, чтобы не оптимизировать полностью
    for (long long i = start; i < stop; ++i) {
        if (i & 1) count -= a;
        else count += a;
    }
    *pcounter = count;
}

double test1(void) {
    auto t0 = std::chrono::high_resolution_clock::now();
    long long cnt1 = 0;
    fun1(val, 0, NUMBER, &cnt1);
    counter = cnt1;
    auto t1 = std::chrono::high_resolution_clock::now();
    double ms = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(t1 - t0).count();
    return ms;
}


int main(int argc, char** argv) {
    std::cout << "NUMBER = " << NUMBER << "\n";
    std::cout << "val = " << val << "\n";

    {
        std::cout << "Running test1 (single-threaded) ...\n";
        double ms = test1();
        std::cout << " test1: time = " << ms << " ms, counter = " << counter << "\n";
    }

}

Пример результата:

Пример выполнения программы

Ассемблер Debug arm:

fun1(int, long long, long long, long long*):
    sub sp, sp, #48
    str w0, [sp, #44]
    str x1, [sp, #32]
    str x2, [sp, #24]
    str x3, [sp, #16]
    str xzr, [sp, #8]
    ldr x8, [sp, #32]
    str x8, [sp]
    b   LBB0_1
LBB0_1:
    ldr x8, [sp]
    ldr x9, [sp, #24]
    subs    x8, x8, x9
    b.ge    LBB0_7
    b   LBB0_2
LBB0_2:
    ldr x8, [sp]
    tbz w8, #0, LBB0_4
    b   LBB0_3
LBB0_3:
    ldrsw   x9, [sp, #44]
    ldr x8, [sp, #8]
    subs    x8, x8, x9
    str x8, [sp, #8]
    b   LBB0_5
LBB0_4:
    ldrsw   x9, [sp, #44]
    ldr x8, [sp, #8]
    add x8, x8, x9
    str x8, [sp, #8]
    b   LBB0_5
LBB0_5:
    b   LBB0_6
LBB0_6:
    ldr x8, [sp]
    add x8, x8, #1
    str x8, [sp]
    b   LBB0_1
LBB0_7:
    ldr x8, [sp, #8]
    ldr x9, [sp, #16]
    str x8, [x9]
    add sp, sp, #48
    ret

ассемблер дебаг x86_64:

fun1(int, long long, long long, long long*):
    pushq   %rbp
    movq    %rsp, %rbp
    movl    %edi, -4(%rbp)
    movq    %rsi, -16(%rbp)
    movq    %rdx, -24(%rbp)
    movq    %rcx, -32(%rbp)
    movq    $0, -40(%rbp)
    movq    -16(%rbp), %rax
    movq    %rax, -48(%rbp)
LBB0_1:
    movq    -48(%rbp), %rax
    cmpq    -24(%rbp), %rax
    jge LBB0_7
    movq    -48(%rbp), %rax
    andq    $1, %rax
    cmpq    $0, %rax
    je  LBB0_4
    movslq  -4(%rbp), %rcx
    movq    -40(%rbp), %rax
    subq    %rcx, %rax
    movq    %rax, -40(%rbp)
    jmp LBB0_5
LBB0_4:
    movslq  -4(%rbp), %rcx
    movq    -40(%rbp), %rax
    addq    %rcx, %rax
    movq    %rax, -40(%rbp)
LBB0_5:
    jmp LBB0_6
LBB0_6:
    movq    -48(%rbp), %rax
    addq    $1, %rax
    movq    %rax, -48(%rbp)
    jmp LBB0_1
LBB0_7:
    movq    -40(%rbp), %rcx
    movq    -32(%rbp), %rax
    movq    %rcx, (%rax)
    popq    %rbp
    retq

ассемблер релиз arm:

fun1(int, long long, long long, long long*):
    sub sp, sp, #16
    str xzr, [sp, #8]
    cmp x1, x2
    b.ge    LBB0_5
    sxtw    x8, w0
    b   LBB0_3
LBB0_2:
    add x9, x9, x8
    str x9, [sp, #8]
    add x1, x1, #1
    cmp x2, x1
    b.eq    LBB0_5
LBB0_3:
    ldr x9, [sp, #8]
    tbz w1, #0, LBB0_2
    sub x9, x9, x8
    str x9, [sp, #8]
    add x1, x1, #1
    cmp x2, x1
    b.ne    LBB0_3
LBB0_5:
    ldr x8, [sp, #8]
    str x8, [x3]
    add sp, sp, #16
    ret

ассемблер релиз x86_64:

fun1(int, long long, long long, long long*):
    pushq   %rbp
    movq    %rsp, %rbp
    movq    $0, -8(%rbp)
    cmpq    %rsi, %rdx
    jle LBB0_15
    movslq  %edi, %rax
    movl    %edx, %r8d
    subl    %esi, %r8d
    movq    %rsi, %rdi
    testb   $1, %r8b
    je  LBB0_6
    movq    -8(%rbp), %rdi
    testb   $1, %sil
    jne LBB0_3
    addq    %rax, %rdi
    jmp LBB0_5
LBB0_3:
    subq    %rax, %rdi
LBB0_5:
    movq    %rdi, -8(%rbp)
    leaq    1(%rsi), %rdi
LBB0_6:
    leaq    -1(%rdx), %r8
    cmpq    %rsi, %r8
    je  LBB0_15
    subq    %rdi, %rdx
    jmp LBB0_8
LBB0_13:
    addq    %rax, %rsi
    movq    %rsi, -8(%rbp)
    addq    $-2, %rdx
    je  LBB0_15
LBB0_8:
    movq    -8(%rbp), %rsi
    testb   $1, %dil
    jne LBB0_9
    addq    %rax, %rsi
    movq    %rsi, -8(%rbp)
    movq    -8(%rbp), %rsi
    testb   $1, %dil
    jne LBB0_13
    jmp LBB0_12
LBB0_9:
    subq    %rax, %rsi
    movq    %rsi, -8(%rbp)
    movq    -8(%rbp), %rsi
    testb   $1, %dil
    jne LBB0_13
LBB0_12:
    subq    %rax, %rsi
    movq    %rsi, -8(%rbp)
    addq    $-2, %rdx
    jne LBB0_8
LBB0_15:
    movq    -8(%rbp), %rax
    movq    %rax, (%rcx)
    popq    %rbp
    retq

Подскажите, может кто-то сталкивался с похожей проблемой)


Ответы (0 шт):