2016-05-13 2 views
2

У меня вопрос о флажках оптимизации GCC и о том, как они работают.C++ GCC Оптимизация Скорость замедляется, когда локальная переменная копируется в глобальную переменную

У меня очень длинный фрагмент кода, который использует все локальные массивы и переменные. В конце кода я копирую содержимое локального массива в глобальный массив. Здесь чрезвычайно разобранный пример моего кода:

uint8_t globalArray[16]={0}; 
void func() 
{ 
    unsigned char localArray[16]={0}; 
    for (int r=0; r<1000000; r++) 
    {  
     **manipulate localArray with a lot of calculations** 
    } 
    memcpy(&globalArray,localArray,16); 
}  

Вот примерная скорость кода в трех различных сценариев:

  1. Без «-O3» оптимизация: 3.203s

  2. С "-O3" оптимизация: 1.457s

  3. С «-O3» оптимизации и без окончательное memcpy(&globalArray,localArray,16); заявление: 0.015s

без копирования локального массива в глобальный массив, код работает почти в 100 раз быстрее. Я знаю, что глобальный массив хранится в памяти, а локальный массив хранится в регистрах. Я задал вопрос:

  1. Почему простое копирование 16 элементов локального массива в глобальный массив вызывает 100-кратное более медленное выполнение? Я искал этот форум и онлайн, и я не могу найти определенного ответа на этот конкретный сценарий.

  2. Есть ли способ, что я могу извлечь содержимое локальной переменной без потери скорости?

Благодарим вас за помощь всем, кто может помочь мне с этой проблемой.

+6

В случае 3, возможно, компилятор удалил все вычисления, поскольку они не вызывают наблюдаемого поведения. Вы можете проверить это, проверив код сборки –

+0

. Вы также можете вернуть указатель localArray из функции, что также помешает компилятору оптимизировать все содержимое функции. Это даст лучшее сравнение. – Conor

+2

@Conor Это неопределенное поведение. – TartanLlama

ответ

7

Без memcpy ваш компилятор, скорее всего, увидит, что localArray никогда не читается, поэтому ему не нужно выполнять какие-либо вычисления в теле цикла.

Возьмите этот код в качестве примера:

uint8_t globalArray[16]={0}; 
void func() 
{ 
    unsigned char localArray[16]={0}; 
    for (int r=0; r<1000000; r++) 
    { 
     localArray[r%16] = r; 
    } 
    memcpy(&globalArray,localArray,16); 
} 

Clang 3.7.1 с -O3 выходами эту сборку:

func():        # @func() 
# BB#0: 
     xorps %xmm0, %xmm0 
     movaps %xmm0, -24(%rsp) 
     #DEBUG_VALUE: r <- 0 
     xorl %eax, %eax 
.LBB0_1:        # =>This Inner Loop Header: Depth=1 
     #DEBUG_VALUE: r <- 0 
     movl %eax, %ecx 
     sarl $31, %ecx 
     shrl $28, %ecx 
     leal (%rcx,%rax), %ecx 
     andl $-16, %ecx 
     movl %eax, %edx 
     subl %ecx, %edx 
     movslq %edx, %rcx 
     movb %al, -24(%rsp,%rcx) 
     leal 1(%rax), %ecx 
     #DEBUG_VALUE: r <- ECX 
     movl %ecx, %edx 
     sarl $31, %edx 
     shrl $28, %edx 
     leal 1(%rax,%rdx), %edx 
     andl $-16, %edx 
     negl %edx 
     leal 1(%rax,%rdx), %edx 
     movslq %edx, %rdx 
     movb %cl, -24(%rsp,%rdx) 
     leal 2(%rax), %ecx 
     movl %ecx, %edx 
     sarl $31, %edx 
     shrl $28, %edx 
     leal 2(%rax,%rdx), %edx 
     andl $-16, %edx 
     negl %edx 
     leal 2(%rax,%rdx), %edx 
     movslq %edx, %rdx 
     movb %cl, -24(%rsp,%rdx) 
     leal 3(%rax), %ecx 
     movl %ecx, %edx 
     sarl $31, %edx 
     shrl $28, %edx 
     leal 3(%rax,%rdx), %edx 
     andl $-16, %edx 
     negl %edx 
     leal 3(%rax,%rdx), %edx 
     movslq %edx, %rdx 
     movb %cl, -24(%rsp,%rdx) 
     leal 4(%rax), %ecx 
     movl %ecx, %edx 
     sarl $31, %edx 
     shrl $28, %edx 
     leal 4(%rax,%rdx), %edx 
     andl $-16, %edx 
     negl %edx 
     leal 4(%rax,%rdx), %edx 
     movslq %edx, %rdx 
     movb %cl, -24(%rsp,%rdx) 
     addl $5, %eax 
     cmpl $1000000, %eax   # imm = 0xF4240 
     jne  .LBB0_1 
# BB#2: 
     movaps -24(%rsp), %xmm0 
     movaps %xmm0, globalArray(%rip) 
     retq 

Для того же кода без memcpy, он выводит это:

func():        # @func() 
# BB#0: 
     #DEBUG_VALUE: r <- 0 
     retq 

Даже если вы ничего не знаете о сборке, это cle чтобы увидеть, что последнее ничего не делает.

+0

Спасибо. Ответил это отлично. –

 Смежные вопросы

  • Нет связанных вопросов^_^