Как выполнение большего количества инструкций может ускорить выполнение - PullRequest
4 голосов
/ 05 октября 2011

Когда я запускаю следующую функцию, я получаю несколько неожиданные результаты.

На моем компьютере приведенный ниже код последовательно выполняется около 6 секунд.Однако, если я раскомментирую строку ";dec [variable + 24]", , следовательно, для выполнения большего количества кода , потребуется около 4,5 секунд для запуска.Почему?

.DATA
variable dq 0 dup(4)
.CODE             

runAssemblyCode PROC
    mov rax, 2330 * 1000 * 1000
start:
    dec [variable]
    dec [variable + 8]
    dec [variable + 16]
    ;dec [variable + 24]
    dec rax
    jnz start
    ret 
runAssemblyCode ENDP 
END

Я заметил, что уже есть похожие вопросы о переполнении стека, но их примеры кода не так просты, как этот, и я не смог найти кратких ответов на этот вопрос.

Я попытался заполнить код инструкциями nop , чтобы выяснить, не является ли это проблемой выравнивания, а также установить привязку к одному процессору.Ни один не имел никакого значения.

Ответы [ 3 ]

3 голосов
/ 05 октября 2011

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

Вставка этой дополнительной инструкции может привести к тому, что она будет планировать инструкции по-другому, что в таком узком цикле может изменить ситуацию. Но это только предположение.

Насколько я вижу, он касается той же строки кэша, что и предыдущая инструкция, поэтому он не является своего рода предварительной загрузкой. Я не могу придумать логического объяснения, но опять же, процессор использует множество недокументированных эвристик и догадок для максимально быстрого выполнения кода, а иногда это означает странные угловые случаи, когда они терпят неудачу, и код медленнее, чем вы ожидаете.

Вы проверяли это на разных моделях процессоров? Было бы интересно посмотреть, если это только на вашем конкретном процессоре, или другие процессоры x86 показывают то же самое.

1 голос
/ 06 октября 2011

bob.s

.data
variable:
    .word 0,0,0,0
    .word 0,0,0,0
    .word 0,0,0,0
    .word 0,0,0,0
    .word 0,0,0,0
    .word 0,0,0,0

.text
.globl runAssemblyCode
runAssemblyCode:
  mov    $0xFFFFFFFF,%eax

start_loop:
  decl variable+0
  decl variable+8
  decl variable+16
  ;decl variable+24
  dec    %eax
  jne    start_loop
  retq

ted.c

#include <stdio.h>
#include <time.h>

void runAssemblyCode ( void );

int main ( void )
{
    volatile unsigned int ra,rb;

    ra=(unsigned int)time(NULL);
    runAssemblyCode();
    rb=(unsigned int)time(NULL);
    printf("%u\n",rb-ra);
    return(0);
}

gcc -O2 ted.c bob.s -o ted

это было с дополнительныминструкция:

00000000004005d4 <runAssemblyCode>:
  4005d4:   b8 ff ff ff ff          mov    $0xffffffff,%eax

00000000004005d9 <start_loop>:
  4005d9:   ff 0c 25 28 10 60 00    decl   0x601028
  4005e0:   ff 0c 25 30 10 60 00    decl   0x601030
  4005e7:   ff 0c 25 38 10 60 00    decl   0x601038
  4005ee:   ff 0c 25 40 10 60 00    decl   0x601040 
  4005f5:   ff c8                   dec    %eax
  4005f7:   75 e0                   jne    4005d9 <start_loop>
  4005f9:   c3                      retq   
  4005fa:   90                      nop

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

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

это заняло около 13 секунд с или без дополнительной инструкции.

и четырехъядерный процессор Phenom 9950

на

Intel® Core (TM) 2 CPU 6300

заняло около 9-10 секунд с дополнительной инструкцией или без нее.

Aдва процессора: Intel (R) Xeon (TM) CPU

заняло около 13 секунд с или без дополнительной инструкции.

На это: Intel (R) Core (TM) 2 Duo CPU T7500

8 секунд с или без.

Все работают под управлением Ubuntu 64 бит 10.04 или 10.10, может быть там 11.04.

Еще несколько машин, 64 бит, ubuntu

Intel (R) Xeon (R) CPU X5450 (8 ядер)

6 секунд с или без дополнительной инструкции.

Intel (R) Xeon (R) CPU E5405 (8 ядер)

9 секунд с или без.

Какова скорость вашей DDR / DRAM в вашей системе?Какой тип процессора вы используете (cat / proc / cpuinfo, если на Linux).

Intel (R) Xeon (R) CPU E5440 (8 ядер)

6 секунд с или без

Ааа, нашел одно ядро, хотя xeon: Intel (R) Xeon (TM) CPU

15 секунд с или без дополнительной инструкции

0 голосов
/ 05 октября 2011

Это не так уж плохо. В среднем полный цикл занимает 2,6 нс, а другой - 1,9 нс. Предполагая, что процессор с частотой 2 ГГц имеет период 0,5 нс, разница составляет около (2.6 - 1.9) / 0.5 = 1 clock cycle на цикл, ничего удивительного.
Разница во времени становится настолько заметной, хотя из-за количества запрошенных вами циклов: 0.5 ns * 2330000000 = 1.2 seconds, наблюдаемая вами разница.

...