Опция GCC -march=native

Почему в некоторых случаях применение опции -march=native замедляет код, генерируемый GCC?

Вот среднее время работы разных бинарников кода ниже, скомпилированных с разными опциями на моей машине (GCC 10.2.0, Clang 9.0.1, Ryzen 3 3200U):

gcc   -O2                     0.125 0.088
gcc   -Ofast                  0.125 0.089
gcc   -O2 -march=native       0.126 0.090
gcc   -Ofast -march=native    0.187 0.127

clang -O2                     0.120 0.081
clang -Ofast                  0.116 0.081
clang -O2 -march=native       0.131 0.094
clang -Ofast -march=native    0.084 0.096

Листинг gcc -O2:

Dump of assembler code for function char_bench:
   0x0000000000001230 <+0>: push   r12
   0x0000000000001232 <+2>: push   rbp
   0x0000000000001233 <+3>: mov    rbp,rsi
   0x0000000000001236 <+6>: push   rbx
   0x0000000000001237 <+7>: mov    rbx,rdi
   0x000000000000123a <+10>:    call   0x1030 <clock@plt>
   0x000000000000123f <+15>:    mov    r12,rax
   0x0000000000001242 <+18>:    xor    eax,eax
   0x0000000000001244 <+20>:    nop    DWORD PTR [rax+0x0]
   0x0000000000001248 <+24>:    cmp    BYTE PTR [rbx+rax*1],0x0
   0x000000000000124c <+28>:    je     0x1253 <char_bench+35>
   0x000000000000124e <+30>:    mov    BYTE PTR [rbp+rax*1+0x0],0x1
   0x0000000000001253 <+35>:    add    rax,0x1
   0x0000000000001257 <+39>:    cmp    rax,0xbebc200
   0x000000000000125d <+45>:    jne    0x1248 <char_bench+24>
   0x000000000000125f <+47>:    call   0x1030 <clock@plt>
   0x0000000000001264 <+52>:    pop    rbx
   0x0000000000001265 <+53>:    pop    rbp
   0x0000000000001266 <+54>:    sub    rax,r12
   0x0000000000001269 <+57>:    pop    r12
   0x000000000000126b <+59>:    ret    
End of assembler dump.

Листинг gcc -Ofast -march=native:

Dump of assembler code for function char_bench:
   0x0000000000001250 <+0>: push   r12
   0x0000000000001252 <+2>: push   rbp
   0x0000000000001253 <+3>: mov    rbp,rsi
   0x0000000000001256 <+6>: push   rbx
   0x0000000000001257 <+7>: mov    rbx,rdi
   0x000000000000125a <+10>:    call   0x1030 <clock@plt>
   0x000000000000125f <+15>:    mov    r12,rax
   0x0000000000001262 <+18>:    xor    eax,eax
   0x0000000000001264 <+20>:    data16 nop WORD PTR cs:[rax+rax*1+0x0]
   0x000000000000126f <+31>:    nop
   0x0000000000001270 <+32>:    cmp    BYTE PTR [rbx+rax*1],0x0
   0x0000000000001274 <+36>:    je     0x127b <char_bench+43>
   0x0000000000001276 <+38>:    mov    BYTE PTR [rbp+rax*1+0x0],0x1
   0x000000000000127b <+43>:    inc    rax
   0x000000000000127e <+46>:    cmp    rax,0xbebc200
   0x0000000000001284 <+52>:    jne    0x1270 <char_bench+32>
   0x0000000000001286 <+54>:    call   0x1030 <clock@plt>
   0x000000000000128b <+59>:    pop    rbx
   0x000000000000128c <+60>:    sub    rax,r12
   0x000000000000128f <+63>:    pop    rbp
   0x0000000000001290 <+64>:    pop    r12
   0x0000000000001292 <+66>:    ret    
End of assembler dump.
#include <stdio.h>
#include <time.h>

#define SIZE 200000000

char C1[SIZE];
char C2[SIZE];

clock_t char_bench(char * const source, char * const dest)
{
    clock_t start = clock();
    
    for(size_t i = 0; i < SIZE; ++i)
        if(source[i])
            dest[i] = 1;
    
    clock_t end = clock();
    
    return end - start;
}

int main()
{
    for(size_t i = 0; i < SIZE; ++i)
    {
        C1[i] = 0;
        C2[i] = 0;
    }
    
    printf("%.3lf\n", char_bench(C1, C2) / (float)CLOCKS_PER_SEC);
    
    for(size_t i = 0; i < SIZE; ++i)
    {
        C1[i] = 1;
        C2[i] = 1;
    }
    
    printf("%.3lf\n", char_bench(C1, C2) / (float)CLOCKS_PER_SEC);
    
    return 0;
}

Понимаю, что бенчмарк синтетический, но разница во времени выполнения всё же удручает.


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