Точно, как “быстро” современные центральные процессоры?

Когда я раньше программировал встроенные системы и рано 8/16-bit ПК (6502, 68K, 8086) у меня был довольно хороший дескриптор на exacly, сколько времени (в наносекундах или микросекундах) каждая инструкция взяла для выполнения. В зависимости от семейства одно (или четыре) циклы, приравненные к одной "памяти, выбирают", и без кэшей для волнения о, Вы могли предположить синхронизации на основе количества включенных доступов памяти.

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

Так, может любой обеспечивать некоторые синхронизации для двух демонстрационных инструкций на (скажем), Core 2 Duo на 2 ГГц. Лучшие и худшие случаи (принимающий ничто в кэше/всем в кэше) были бы полезны.

Инструкция № 1: Добавьте один 32-разрядный регистр к секунде.

Инструкция № 2: Переместите 32-разрядное значение от регистра до памяти.

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

Редактирование № 2: много ответов с интересными моментами, но никто (все же) не подавил число, измеряемое вовремя. Я ценю существуют "сложности" к вопросу, но продвигаются: Если мы можем оценить количество тюнеров фортепьяно в Нью-Йорк Сити, мы должны смочь оценить время выполнения кода...

Возьмите следующий (немой) код:

int32 sum = frigged_value();

// start timing
 for (int i = 0 ; i < 10000; i++)
 {
   for (int j = 0 ; j < 10000; j++)
   {
     sum += (i * j)
   }
   sum = sum / 1000;
 }

// end timing

Как мы можем оценить, сколько времени это возьмет для выполнения... 1 фемтосекунда? 1 gigayear?

18
задан Peter Cordes 14 November 2019 в 02:54
поделиться

14 ответов

Современные процессоры, такие как Core 2 Duo, который Вы упоминаете, и суперскалярные и , конвейерно обработал . Они имеют несколько модулей выполнения на ядро и на самом деле работают над больше чем одной инструкцией за один раз на ядро; это - суперскалярная часть. Конвейерная часть означает, что существует задержка от того, когда инструкция прочитана в и "дана" к тому, когда она завершает выполнение и на этот раз варьируется в зависимости от зависимостей между той инструкцией и другими перемещающимися через другие модули выполнения одновременно. Так, в действительности синхронизация любой данной инструкции варьируется в зависимости от того, что вокруг этого и в зависимости от чего это. Это означает, что данная инструкция имеет вид лучшего случая и худшее время выполнения случая на основе многих факторов. Из-за нескольких модулей выполнения у Вас может на самом деле быть больше чем одна инструкция, завершающая выполнение на базовые часы, но иногда существует несколько часов между завершениями, если конвейер должен остановить ожидание памяти или зависимостей в конвейерах.

Все вышеупомянутое только от представления самого ядра процессора. Затем у Вас есть взаимодействия с кэшами и конкуренцией для пропускной способности с другими ядрами. Блок шинного интерфейса из ЦП имеет дело с получением инструкций и данных, питаемых в ядро и выведение результатов назад из ядра через кэши к памяти.

Грубые эмпирические правила порядка величины, которые будут взяты с мелкой частицей соли:

  • Регистр для Регистрации операций берут 1 ядро часы для выполнения. Это должно обычно быть консервативно тем более, что больше из них появляется в последовательности.
  • связанная с памятью загрузка и операции хранилища берут 1 шина памяти часы для выполнения. Это должно быть очень консервативно. С высоким уровнем удачного обращения в кэш это будет больше похоже 2 шина ЦП часы, который является тактовой частотой шины между ядром процессора и кэшем, но не обязательно часами ядра.
40
ответ дан 30 November 2019 в 05:37
поделиться

Почти невозможно обеспечить точную информацию синхронизации, которую Вы ожидаете способом, что это будет ПОЛЕЗНО для Вас.

следующие понятия влияют на синхронизацию инструкции; некоторые могут варьироваться с момента до момента:

  • разложение Micro-op
  • Операция, конвейерно обрабатывающая
  • Суперскалярное выполнение
  • Исполнение с изменением последовательности
  • SMT / выполнение SMP
  • режим С плавающей точкой
  • Предсказание ветвлений / упреждающая выборка
  • задержка Кэша
  • Задержка при обращении к памяти
  • , Тактовая частота, регулирующая
  • и т.д.

, Консультируется с книгой по архитектуре современного компьютера при необходимости в дальнейшем объяснении на вышеупомянутых понятиях.

лучший способ измерить скорость Вашего кода (удивление!) для измерения скорости кода, выполняющего ту же рабочую нагрузку и при тех же условиях, поскольку Вы ожидаете это к когда "в реальном мире".

14
ответ дан 30 November 2019 в 05:37
поделиться

Дело не в этом простой. Синхронизация для Ваших двух инструкций не поможет Вам измерить производительность большего набора инструкций очень. Поэтому современные процессоры могут выполнить много операций параллельно и иметь большие кэши, таким образом, "перемещение значения к памяти" происходит за один раз вполне удаленное из выполнения инструкции.

Так, лучший случай является нулем (при выполнении параллельно с другими инструкциями). Но как это помогает Вам?

Этот веб-страница показывает некоторые сравнительные тесты, включая некоторые результаты %MIPS/MHz. Как Вы видите, на многих сравнительных тестах существуют многоадресные команды, выполняемые на такт. Диаграммы также показывают эффекты скорости памяти и размера кэша.

7
ответ дан 30 November 2019 в 05:37
поделиться

Используя описание в основном на основе архитектуры Intel Pentium, для прерывания очень очень длинной истории:

  • процессор имеет много "модулей выполнения", которые могут выполнить различные типы 'микрооперации в секунду'; инструкции могут быть разделены на несколько микроопераций в секунду
  • различные модули выполнения, по существу выполненные в параллели
  • , каждый micro-op связывает соответствующий модуль выполнения для определенного числа тактов поэтому между тем, никакая другая инструкция не может использовать тот модуль выполнения: например, "плавающая точка добавляет", может объединиться, "FP выполняют" единицу для 2 тактов
  • , модули выполнения сгруппированы "портом" и каждым тактом, новый micro-op может быть отправлен в каждый порт (предполагающий, что соответствующий модуль выполнения является бесплатным в тот момент); некоторые единицы могут также быть отправлены "дополнительный op" на полпути через цикл; так каждый такт, определенное число операции в секунду может запускаться выполнение;
  • процессор может переупорядочить микрооперацию в секунду, где это не повреждает зависимости (или где результат может все еще быть восстановлен) использовать в своих интересах, какие модули выполнения являются бесплатными в данный момент
  • , таким образом, инструкции могут выполняться параллельно, но какой, части которого инструкции выполняются в любой момент, вполне сложная ситуация
  • , полное время для данной инструкции таким образом зависит от того, сколько времени это должно было "ожидать" необходимых модулей выполнения для становления доступным, фактическое время, когда они операция в секунду потратили работу данных единиц плюс любое дополнительное время, требуемое "связать результат"

, Так как синхронизация инструкции зависит от окружающих инструкций, на практике, это является обычно лучшим к [1 119] время репрезентативная часть кода , чем пытаются волноваться об отдельных инструкциях. Однако:

  • Intel (и по-видимому другие производители) публикует список инструкции пропускная способность и задержка синхронизации
  • , пропускная способность является количеством тактов, на самом деле необходимых на соответствующем модули (модулях) выполнения
  • , задержка является "худшим случаем" количество требуемых тактов, после того как инструкция начинает выполняться, прежде чем результат того выполнения будет доступен, как введено другой инструкции

Так, например, если, скажем, плавающая точка добавляет и умножает инструкции, у каждого есть пропускная способность 2 и задержка 5 (на самом деле, для умножаются, немного больше, что я думаю), который означает, что добавление регистра к себе или умножению его отдельно, вероятно, возьмет два такта (так как нет никаких других зависимых значений), тогда как добавление его, результат предыдущего умножения возьмет что-то как или немного меньше чем 2+5 тактов, завися, где Вы запускаете/заканчиваете синхронизировать, и на всех видах других вещей. (Во время некоторых из тех тактов другой добавляет/умножает, что операция могла происходить, таким образом, спорно, сколько циклов Вы на самом деле приписываете отдельным add/mutliply инструкциям так или иначе...)

, О, и так же, как конкретный пример. Поскольку следование коду Java

public void runTest(double[] data, double randomVal) {
  for (int i = data.length-1; i >= 0; i--) {
    data[i] = data[i] + randomVal;
  }
}

Горячая точка 1.6.12 компиляций JIT последовательность внутреннего цикла к следующему коду Intel, состоя из load-add-store для каждого положения в массиве (при этом 'randomVal' сохранен в XMM0a в этом случае):

  0b3     MOVSD  XMM1a,[EBP + #16]
  0b8     ADDSD  XMM1a,XMM0a
  0bc     MOVSD  [EBP + #16],XMM1a
  0c1     MOVSD  XMM1a,[EBP + #8]
  0c6     ADDSD  XMM1a,XMM0a
  0ca     MOVSD  [EBP + #8],XMM1a
  ...

каждая группа [1 124] load-add-store, кажется, берет 5 тактов .

8
ответ дан 30 November 2019 в 05:37
поделиться

Вид прогноза, который Вы просите, безнадежен.

, Если Вы хотите эмпирическое правило, вот некоторые эмпирические правила:

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

  • Во время это берет для получения слова от RAM, процессор может выполнить тысячи инструкций (это число варьируется несколькими порядками величины в зависимости от деталей аппаратных средств). Удостоверьтесь, что это происходит только в холодном кэше; иначе ничто иное не имеет значения.

  • при работе x86 центральных процессоров нет достаточных регистров. Попытайтесь не иметь больше чем 5 живых переменных в своем коде в любой момент. Или еще лучше, переместитесь в AMD64 (x86_64) и удвойте количество регистров. С 16 регистрами и параметрами передал в регистрах, можно выйти из волнения по поводу регистров.

было время, когда каждый год я буду спрашивать архитектора, какие эмпирические правила я должен использовать для предсказания стоимости кода, который генерируют мои компиляторы. Я остановился, потому что прошлый раз, когда я получил полезный ответ, был в 1999. (Ответ был, "удостоверяются, что Ваши циклы помещаются в буфер восстановления последовательности". Все те, кто знает то, что буфер восстановления последовательности, могут теперь повысить Ваши руки. Бонусные очки, если можно обнаружить размер буфера восстановления последовательности на каком-либо компьютере, Вы в настоящее время используете.)

7
ответ дан 30 November 2019 в 05:37
поделиться

Эта единственная часть ответов Вашего вопроса, но я нашел эту таблицу из Википедии на местность ссылки полезный. Это описывает скорость доступа к и объема памяти в разных уровнях иерархии памяти, с помощью приблизительных времен 2006 года:

  • регистры ЦП (8-32 регистра) †“немедленный доступ (0-1 такт)
  • кэши ЦП L1 (32 кибибайта к 128 кибибайтам) †“быстрый доступ (3 такта)
  • кэши ЦП L2 (128 кибибайт к 12 мебибайт) †“немного более медленный доступ (10 тактов)
  • Основная физическая память (RAM) (256 мебибайт к 4 гибибайтам) †“медленный доступ (100 тактов)
  • Диск (файловая система) (1 гибибайт к 1 тебибайту) †“очень медленный (10 000 000 тактов)
  • Удаленная Память (таких как другие компьютеры или Интернет) (практически неограниченный) †“скорость варьируется
5
ответ дан 30 November 2019 в 05:37
поделиться

Современные процессоры делают еще более хитрые вещи.

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

переименование Регистра. Процессоры часто имеют больше физических регистров, чем адресуемые регистры в их системе команд (так называемые "архитектурные" регистры). Это может быть или для обратной совместимости, или просто включить эффективную кодировку инструкции. Как прогоны программы, процессор "переименует" архитектурные регистры, которые он использует для любых физических регистров, свободны. Это позволяет процессору понимать больше параллелизма, чем существовал в исходной программе.

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

микроархитектура Intel P6 делает и выполнение с изменением последовательности и переименование регистра. Архитектура Core 2 является последней производной P6.

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

7
ответ дан 30 November 2019 в 05:37
поделиться

Можно загрузить Intel 64 и руководства IA-32 здесь .

, Но то, в чем Вы действительно нуждаетесь, является материалом от Вуаль Agner .

у Него есть много дополнительных infos, например, его руководство "Таблицы инструкции: Списки задержек инструкции, пропускной способности и разбивок микрооперации для Intel и центральных процессоров AMD" .

Или тестовые программы для подсчета тактов (он использует счетчик метки времени ).

4
ответ дан 30 November 2019 в 05:37
поделиться

Много хороших ответов на этом потоке уже, но одна тема до сих пор не упоминается: misprediction ответвления.

, поскольку все современные процессоры являются конвейерными, когда декодер инструкции сталкивается с инструкцией как "переход, если равный", это понятия не имеет, какой путь инструкция перейдет, и таким образом, это просто предположит. Это затем продолжает подавать инструкции в конвейер на основе того предположения. Если это сделало корректный прогноз, thruput и задержка команды перехода являются по существу нулем. Если это высказывает неправильное предположение, thruput и задержка той же команды перехода могли бы быть 50 или 100 циклы.

Примечание, что та же инструкция может иметь "нулевую стоимость" в первый раз, когда это выполняется в цикле и действительно огромной стоимости в следующий раз, та же инструкция выполняется!

4
ответ дан 30 November 2019 в 05:37
поделиться

Все, в чем Вы нуждаетесь, находится в соответствующих руководствах ЦП. И AMD и Intel имеют PDF в наличии на их веб-сайте, описывающем задержки каждой инструкции.

Просто имеют в виду сложность современного ЦП. Они не выполняют одну инструкцию за один раз, они могут загрузить 3-4 инструкции на цикл, и почти все инструкции являются конвейерными поэтому, когда следующие инструкции загружаются, текущие нигде не рядом закончены. Это также переупорядочивает инструкции позволить, чтобы более эффективное планировало. Современный ЦП может легко иметь 50 происходящих инструкций за один раз.

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

3
ответ дан 30 November 2019 в 05:37
поделиться

Интересное кавычка от Alan Kay в 2004 :

Так же, как в стороне, чтобы дать Вам интересный benchmark— примерно в той же системе, примерно оптимизировал тот же путь, сравнительный тест с 1979 в Xerox PARC работает только в 50 раз быстрее сегодня. Закон Moore’s дал нам где-нибудь между улучшением 40 000 и 60 000 раз в то время. Так there’s приблизительно фактор 1 000 в эффективности, которая была потеряна плохими архитектурами ЦП.

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

2
ответ дан 30 November 2019 в 05:37
поделиться

Как Doug уже отметил, лучший случай является нулем (суперскалярный процессор, несколько модулей выполнения, данные уже в кэше L1).

худший случай до нескольких миллисекунд (когда ОС обрабатывает отсутствие страницы и должна выбрать данные/инструкцию из диска). Исключая диск/свопинг это все еще зависит от того, есть ли у Вас машина NUMA, какой вид топологии это имеет, в котором узле памяти находятся данные, существует ли параллельный доступ от другого ЦП (блокировка шины и протоколы синхронизации кэша), и т.д.

2
ответ дан 30 November 2019 в 05:37
поделиться

Я рекомендую загрузить руководство по программной оптимизации AMD .

3
ответ дан 30 November 2019 в 05:37
поделиться

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

0
ответ дан 30 November 2019 в 05:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: