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
Подскажите, может кто-то сталкивался с похожей проблемой)
