Я не буду пытаться с уверенностью ответить, сколько циклов (3 или 10) потребуется для выполнения каждой итерации, но я объясню, как с помощью можно можно получить 3 цикла за итерацию ,
(Обратите внимание, что это касается процессоров в целом, и я не делаю ссылок, относящихся к процессорам AMD.)
Основные понятия:
Большинство современных (не встроенных) процессоров сегодня являются как суперскалярными, так и неупорядоченными. Мало того, что могут выполнять несколько (независимых) инструкций параллельно, но они могут переупорядочивать инструкции, чтобы сломать зависимости и тому подобное.
Давайте разберем ваш пример:
label:
mov (%rsi), %rax
adc %rax, (%rdx)
lea 8(%rdx), %rdx
lea 8(%rsi), %rsi
dec %ecx
jnz label
Первое, на что нужно обратить внимание, это то, что последние 3 инструкции перед веткой являются независимыми:
lea 8(%rdx), %rdx
lea 8(%rsi), %rsi
dec %ecx
Таким образом, процессор может выполнять все 3 из них параллельно.
Другое дело так:
adc %rax, (%rdx)
lea 8(%rdx), %rdx
Кажется, существует зависимость от rdx
, которая не позволяет двум работать параллельно. Но на самом деле это ложная зависимость , потому что вторая инструкция на самом деле не
зависит от вывода первой инструкции. Современные процессоры могут переименовать регистр rdx
, чтобы эти две инструкции могли быть переупорядочены или выполнены параллельно.
То же самое относится к регистру rsi
между:
mov (%rsi), %rax
lea 8(%rsi), %rsi
Таким образом, в итоге, 3 цикла (потенциально) достижимы следующим образом (это только один из нескольких возможных порядков):
1: mov (%rsi), %rax lea 8(%rdx), %rdx lea 8(%rsi), %rsi
2: adc %rax, (%rdx) dec %ecx
3: jnz label
* Конечно, я слишком упрощаю вещи для простоты. На самом деле задержки, вероятно, длиннее, и между разными итерациями цикла накладываются друг на друга.
В любом случае это может объяснить, как можно получить 3 цикла. Что касается того, почему вы иногда получаете 10 циклов, то для этого может быть масса причин: неправильное прогнозирование ветвления, какой-то случайный конвейерный пузырь ...