Та метрика, которую мы называем «загрузкой процессора» на самом деле многими людьми понимается не совсем верно. Что же такое «загрузка процессора»? Это то, насколько занят наш процессор? Нет, это не так. Да-да, я говорю о той самой классической загрузке CPU, которую показывают все утилиты анализа производительности — от диспетчера задач Windows до команды top в Linux.

Вот что может означать «процессор загружен сейчас на 90%»? Возможно, вы думаете, что это выглядит как-то так:



А на самом деле это выглядит вот так:



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

Что это означает для вас? Понимание того, какое количество времени процессор действительно выполняет некоторые операции, а какое — лишь ожидает данные, иногда даёт возможность изменить ваш код, уменьшив обмен данных с оперативной памятью. Это особенно актуально в нынешних реалиях облачных платформ, где политики автоматического масштабирования иногда напрямую завязаны на загрузку CPU, а значит каждый лишний такт «холостой» работы стоит нам вполне реальных денег.

Что же такое загрузка процессора на самом деле?


Та метрика, которую мы называем «загрузкой процессора» на самом деле означает нечто вроде «время не-простоя»: то есть это то количество времени, которое процессор провёл во всех потоках кроме специального «Idle»-потока. Ядро вашей операционной системы (какой бы она ни была) измеряет это количество времени при переключениях контекста между потоками исполнения. Если произошло переключение потока выполнения команд на не-idle поток, который проработал 100 милисекунд, то ядро операционки считает это время, как время, потраченное CPU на выполнение реальной работы в данном потоке.

Эта метрика впервые появилась в таком виде одновременно с появлением операционных систем с разделением времени. Руководство программиста для компьютера в лунном модуле корабля «Апполон» (передовая на тот момент система с разделением времени) называла свой idle-поток специальным именем «DUMMY JOB» и инженеры сравнивали количество команд, выполняемых этим потоком с количеством команд, выполняемых рабочими потоками — это давало им понимание загрузки процессора.

Так что в этом подходе плохого?

Сегодня процессоры стали значительно быстрее, чем оперативная память, а ожидание данных стало занимать львиную долю того времени, которое мы привыкли называть «временем работы CPU». Когда вы видите высокий процент использования CPU в выводе команды top, то можете решить, что узким местом является процессор (железка на материнской плате под радиатором и кулером), хотя на самом деле это будет совсем другое устройство — банки оперативной памяти.

Ситуация даже ухудшается со временем. Долгое время производителям процессоров удавалось наращивать скорость их ядер быстрее, чем производители памяти увеличивали скорость доступа к ней и уменьшали задержки. Где-то в 2005-ом году на рынке появились процессоры с частотой 3 Гц и производители сконцентрировались на увеличении количества ядер, гипертрейдинге, много-сокетных конфигурациях — и всё это поставило ещё большие требования по скорости обмена данных! Производители процессоров попробовали как-то решить проблему увеличением размера процессорных кэшей, более быстрыми шинами и т.д. Это, конечно, немного помогло, но не переломило ситуацию кардинально. Мы уже ждём память большую часть времени «загрузки процессора» и ситуация лишь ухудшается.

Как же понять, чем на самом деле занят процессор


Используя аппаратные счетчики производительности. В Linux они могут быть прочитаны с помощью perf и других аналогичных инструментов. Вот, например, замер производительности всей системы в течении 10 секунд:

# perf stat -a -- sleep 10

 Performance counter stats for 'system wide':

     641398.723351      task-clock (msec)         #   64.116 CPUs utilized            (100.00%)
           379,651      context-switches          #    0.592 K/sec                    (100.00%)
            51,546      cpu-migrations            #    0.080 K/sec                    (100.00%)
        13,423,039      page-faults               #    0.021 M/sec                  
 1,433,972,173,374      cycles                    #    2.236 GHz                      (75.02%)
   <not supported>      stalled-cycles-frontend  
   <not supported>      stalled-cycles-backend   
 1,118,336,816,068      instructions              #    0.78  insns per cycle          (75.01%)
   249,644,142,804      branches                  #  389.218 M/sec                    (75.01%)
     7,791,449,769      branch-misses             #    3.12% of all branches          (75.01%)

      10.003794539 seconds time elapsed

Ключевая метрика здесь это "количество инструкций за такт" (insns per cycle: IPC), которое показывает, сколько инструкций в среднем выполнил процессор на каждый свой такт. Упрощённо: чем больше это число, тем лучше. В примере выше это число равно 0.78, что, на первый взгляд кажется не таким уж плохим результатом (78% времени выполнялась полезная работа?). Но нет, на этом процессоре максимально возможным значением IPC могло бы быть 4.0 (это связано со способом получения и выполнения инструкций современными процессорами). То есть наше значение IPC (равное 0.78) составляет всего 19.5% от максимально возможной скорости выполнения инструкций. А в процессорах Intel начиная со Skylake максимальное значение IPC уже равно 5.0.

В облаках


Когда вы работаете в виртуальном окружении, то можете и не иметь доступа к реальным счетчикам производительности (это зависит от используемого гипервизора и его настроек). Вот статья о том, как это работает в Amazon EC2.

Интерпретация данных и реагирование


Если у вас IPC < 1.0, то я вас поздравляю, ваше приложение простаивает в ожидании данных от оперативной памяти. Вашей стратегией оптимизации производительности в данном случае будет не уменьшение количества инструкций в коде, а уменьшение количества обращений к оперативной памяти, более активное использование кэшей, особенно на NUMA-системах. С аппаратной точки зрения (если вы можете на это влиять) будет разумным выбрать процессоры с большими размерами кэшей, более быструю память и шину.

Если у вас IPC > 1.0, то ваше приложение страдает не столько от ожидания данных, сколько от чрезмерного количества выполняемых инструкций. Ищите более эффективные алгоритмы, не делайте ненужной работы, кэшируйте результаты повторяемых операций. Применение инструментов построения и анализа Flame Graphs может быть отличным способом разобраться в ситуации. С аппаратной точки зрения вы можете использовать более быстрые процессоры и увеличить количество ядер.

Как вы видите, я провёл черту по значению IPC равному 1.0. Откуда я взял это число? Я рассчитал его для своей платформы, а вы, если не доверяете моей оценке, можете рассчитать его для своей. Для этого напишите два приложения: одно должно загружать процессор на 100% потоком выполнения инструкций (без активного обращения к большим блокам оперативной памяти), а второе должно наоборот активно манипулировать данным в ОЗУ, избегая тяжелых вычислений. Замерьте IPC для каждого из них и возьмите среднее. Это и будет примерная переломная точка для вашей архитектуры.

Что инструменты мониторинга производительности на самом деле должны показывать


Я считаю, что каждый инструмент мониторинга производительности должен показывать значение IPC рядом с загрузкой процессора. Это сделано, например, в инструменте tiptop под Linux:

tiptop -                  [root]
Tasks:  96 total,   3 displayed                               screen  0: default

  PID [ %CPU] %SYS    P   Mcycle   Minstr   IPC  %MISS  %BMIS  %BUS COMMAND
 3897   35.3  28.5    4   274.06   178.23  0.65   0.06   0.00   0.0 java
 1319+   5.5   2.6    6    87.32   125.55  1.44   0.34   0.26   0.0 nm-applet
  900    0.9   0.0    6    25.91    55.55  2.14   0.12   0.21   0.0 dbus-daemo

Другие причины неверной трактовки термина «загрузка процессора»


Процессор может выполнять свою работу медленнее не только из-за потерь времени на ожидание данных из ОЗУ. Другими факторами могут быть:

  • Перепады температуры процессора
  • Вариирование частоты процессора технологией Turboboost
  • Вариирование частоты процессора ядром ОС
  • Проблема усреднённых расчётов: 80% средней загрузки на периоде измерений в минуту могут не быть катастрофой, но могут и прятать в себе скачки до 100%
  • Спин-локи: процессор загружен выполнением инструкций и имеет высокий IPC, но на самом деле приложение стоит в спин-локах и не выполняет реальной работы

Выводы


Загрузка процессора стала сегодня существенно недопонимаемой метрикой: она включает в себя время ожидания данных от ОЗУ, что может занимать даже больше времени, чем выполнение реальных команд. Вы можете определить реальную загрузку процессора с помощью дополнительных метрик, таких, как количество инструкций на такт (IPC). Значения меньшие, чем 1.0 говорят о том, что вы упираетесь в скорость обмена данными с памятью, а большие — свидетельствуют о большой загруженности процессора потоком инструкций. Инструменты замера производительности должны быть улучшены для отображения IPC (или чего-то аналогичного) непосредственно рядом с загрузкой процессора, что даст пользователю полное понимание ситуации. Имея все эти данные, разработчики могут предпринять некоторые меры по оптимизации своего кода именно в тех аспектах, где это принесёт наибольшую пользу.
Поделиться с друзьями
-->

Комментарии (61)


  1. Pilat
    22.05.2017 17:08
    +1

    Естественный показатель — это шум от вентиляторов. Добавить датчик шума, откалибровать — и абсолютно точный результат. Кроме процессоров типа i7-7700k, конечно.


    1. Akon32
      22.05.2017 17:15
      +8

      Может, лучше электросчётчик?


    1. Carburn
      22.05.2017 19:06
      +1

      Скорость вращения вентилятора зависит от температуры. Легче температуру процессора смотреть. Эти значения будут не точными


      1. Pilat
        22.05.2017 19:30
        +4

        Зато вентиляторы можно распознавать на слух без дополнительных устройств.


        1. ozonar
          23.05.2017 08:00

          Температуру можно тоже распознавать без дополнительных устройств.


        1. Singaporian
          23.05.2017 08:05
          +3

          В системах, где вентиляторы вообще есть :-) А если их нет — считай остался без «мониторинга».


        1. Igor_O
          23.05.2017 11:38

          Но многие материнки рулят скоростью вентилятора по ступенькам порядка 5 градусов с большим гистерезисом на снижение скорости, особенно, если загрузка процессора упала не сразу до 0.
          Зато когда что-нибудь ночью считается или рендерится, пока спишь, сразу просыпаешься, как только уровень шума уменьшился…


      1. sumanai
        23.05.2017 17:01

        Скорость вращения вентилятора зависит от температуры.

        Я свои напрямую от БП записал, так как материнка тупая в плане управления вентиляторами, и везде достаточно минимальных оборотов. Так что этот способ не везде доступен ((


    1. gxcreator
      23.05.2017 12:47

      Ничего не надо собирать и калибровать, достаточно смотреть на энергопотребление.


      1. Pilat
        23.05.2017 13:30

        Энергопотребление чего? Матплаты, памяти, видеокарты, дисков?


        1. gxcreator
          23.05.2017 13:45

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


          1. Pilat
            23.05.2017 15:03

            А как его замерить?


            1. Igor_O
              23.05.2017 15:58

              Теоретически, микруха, управляющая VRM, умеет по i2c рассказывать параметры своей работы, из которых, теоретически, можно высчитать напряжение и потребляемую мощность… Но это надо в регистрах i2c копаться — вариантов VRM есть несколько, регистры могут отличаться.
              С другой стороны, есть готовые тулзы у MS и у Intel, которые как-то оценивают энергопотребление процессора «в реальном времени».


              1. gxcreator
                23.05.2017 16:22

                Утилиты типа HWMonitor умеют это делать.


                1. Igor_O
                  23.05.2017 18:16

                  Но тут именно момент, что для многих этих инструментов заявляется именно не измеренное энергопотребление, а вычисленная по каким-то параметрам оценка энергопотребления.
                  Хотя, вроде как на некоторых серверных платформах есть способ непосредственно через мониторинг смотреть энергопотребление процессора.
                  (но когда я однажды участвовал в разработке 4-х процессорной платы, у нас, кажется, мониторинг энергопотребления процессоров предусмотрен не был...)


                  1. gxcreator
                    23.05.2017 18:39
                    +1

                    Как вариант можно ваттметр в цепь питания процессора впаять/вставить.


  1. Akon32
    22.05.2017 17:22
    +3

    на этом процессоре максимально возможным значением IPC могло бы быть 4.0 (это связано со способом получения и выполнения инструкций современными процессорами).

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

    Как вы видите, я провёл черту по значению IPC равному 1.0.

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


    P.S. "IPC — instructions per cycle": Мне казалось, понятия "цикл" и "такт" означают разное.


    1. tangro
      22.05.2017 17:42

      Мне казалось, понятия «цикл» и «такт» означают разное.

      Русская Википедия не имеет перевода статьи Instruction cycle. Люди на StackExange говорят, что правильнее «такт».


      1. PsyHaSTe
        24.05.2017 11:30

        А разве IPC это не per clock?


    1. Igor_O
      23.05.2017 11:23

      Мне казалось, понятия «цикл» и «такт» означают разное

      Очень зависит от переводчика и контекста. В заграничном языке частота процессора называется «clock speed», т.е. скорость часов. Соответственно, меряется в «оборотах (которые не rotation, а cycle) в секунду». Различие между циклами и тактами, теоретически, может возникнуть на стыке цифры и аналога, где на один цикл синусоиды может приходиться несколько отсчетов… Но живьем такого никогда не встречал.
      В общем случае «цикл процессора» и «такт процессора» — синонимы.
      Непонятно, почему бы не загрузить суперскалярный процессор...

      Загрузить суперскалярный процессор «на полную» можно только специально подобранным набором инструкций без ветвлений, переходов и обращений в память. 4 инструкции за такт возникают за счет конвейеров и того факта, что после загрузки команды в конвейер, уже на следующем такте туда можно грузить следующую инструкцию (условно, примерно, не совсем так, но...). Но, конвейер имеет глубину для, например, современных интелов, больше 20 команд. Следовательно, любой «промах» в предсказании ветвления означает, что у нас значительная часть команд, которые успели загрузиться в конвейер, нужно выкинуть и начать грузить конвейер по-новой командами из другой ветки. Опять же, сейчас оно не прямо вот совсем так устроено, принимаются меры для борьбы и куча страшных аббревиатур: распараллеливание декодирования команд, распараллеливание выполнения микрокоманд, переупорядочивание микрокоманд, чтобы максимальное количество выполнялось параллельно и т.д.


      1. Akon32
        23.05.2017 12:10
        +1

        Насколько я понимаю, автор утверждает, что "максимальное количество команд выполнялось бы параллельно" — это плохо, и это кажется мне странным. Если конвейер работает с максимальной производительностью, например перемножая небольшие вектора или матрицы 4х4, то что, вычисления нужно разбавлять доступами в память, чтобы обеспечить IPC=1 ?


      1. Aingis
        23.05.2017 13:16

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

        Если процессоры так недогружены, то можно сделать «процессор Шрёдингера», то есть выполнять обе ветки, пока не определится результаты какой из них взять. Впрочем, наверняка до этого уже додумались. И конечно не спасёт при больших разветвлениях.


        1. Igor_O
          23.05.2017 14:37

          «процессор Шрёдингера»

          На сколько я помню, что-то такое пробовали делать. Но, сильно широко не применяется. Даже один из самых ранних алгоритмов предсказания ветвлений от IBM «попадал» больше, чем в 90% случаев, а некоторые из современных алгоритмов в некоторых задачах «угадывают» больше 97% ветвлений.


  1. yusman
    22.05.2017 17:53

    Спасибо за статью. А есть какие то способы изменить IPC под Виндой?


    1. QDeathNick
      22.05.2017 17:55

      Да, хотелось бы тоже измерить


      1. tangro
        22.05.2017 17:59

        Ну, вроде интеловский VTune умеет измерять обратную метрику (CPI)


        1. igentuman
          22.05.2017 18:49

          VTune стоит страшных денег. Вроде бы Intel PCM может добавить метрику в родной Windows Perfmon. Но я его скомпилить не могу, а скомпиленого нигде не валяется.


          1. igentuman
            22.05.2017 20:06

            А вот скомпилировал, но оказывается, что АМД процессоры не поддерживаются. Жаль.


            1. Salabar
              22.05.2017 21:22

              Есть штука под названием CodeXL, правда я там непосредственно метрики под названием IPC не видел.


          1. DustCn
            23.05.2017 12:45

            Это в районе 10тыр за лицензию, или вообще на халяву за академическую лицуху? Видемо интелу пора доплачивать за втюн.


  1. f1inx
    22.05.2017 18:15
    +2

    Небольшое пояснение на то, что измеряется в качестве загрузки CPU для процесса.

    В моменты времени когда может осуществляться принудительное переключение контекста задачи (т.е. 1 раз за JIFFY) происходит инкремент в структуре task активных в данный момент задач их load_time. Поэтому если по каким либо причинам переключение задач окрашено данная статистика может «безбожно» врать. Т.е. мы, например, можем сделать искусственный процесс, который будет на 100% загружать ресурсы CPU четко между JIFFY затем переключаться в режиме I/O SHCHEDUILIG на короткое время на другой процесс и результатом будет 0% загрузка по данным TOP.


  1. f1inx
    22.05.2017 18:28
    +4

    BTW непонятно, почему автор считает IPC>1 проблемой производительности?

    Проблема производительности это скорее IPC не близко к максимально возможному для данной архитектуры CPU.
    Конечно для окончательного вывода требуется более комплексный анализ алгоритма, оптимальности загрузки внешних шин, кэшей, page faults, branch miss predictions, interrupt rate, trap/exception/taskswitch/cpu migration rate.


    1. DaylightIsBurning
      22.05.2017 19:20
      +1

      подозреваю, что имелось ввиду, что если IPC>1 — улучшить perfromance можно лишь изменением алгоритма, а не оптимизацией памяти/ввода.


      1. novice2001
        23.05.2017 00:04
        +1

        Это бред. Только изменением алгоритма улучшить производительность можно только в случае, когда IPC=MaxIPC, или очень близок к этому.
        А с другой стороны, как можно оптимизировать memory/IO, не меняя алгоритма?

        В обоих случаях придется изменить хотя бы реализацию одного и того же алгоритма.


    1. hdfan2
      23.05.2017 07:00

      По-моему, это что-то типа эвристики — если IPC меньше примерно 1, то лучше оптимизировать в/в, а если больше, то лучше оптимизировать алгоритмы. Но ничто не мешает оптимизировать и то, и другое при любом IPC, просто отдача будет меньше.


      1. f1inx
        24.05.2017 11:31

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


      1. f1inx
        24.05.2017 11:37

        Обычно бывает наоборот, если у нас большие задержки на I/O, то для увеличения IPC нужно поместить, как можно больше вычислительных инструкций не связанных с необходимым I/O между I/O инструкциями.


  1. Jogger
    22.05.2017 20:04

    >>на этом процессоре максимально возможным значением IPC могло бы быть 4.0

    Простите за нубский вопрос — а как определить максимум для своего процессора?


    1. novice2001
      22.05.2017 23:58

      Естественно, из документации производителя.


    1. dimaleks
      23.05.2017 11:21
      +3

      Вопрос к сожалению не нубский, а очень непростой. Сейчас в процессоре можно выделить frontend и backend: первый загружает команды из кэша, декодирует их и отправляет на выполнение в один из портов. Обычно производители публикуют информацию по архитектуре своих процессоров с указанием того, сколько и каких инструкций он может выполнить на том или ином порте и сколько инструкций можно загрузить и декодировать за такт.
      Но это такие «рафинированные» цифры, которые никак не учитывают out-of-order execution, branch prediction, кэш инструкций и т.д. В реальности получить цифры, хоть сколько-то близкие к 4.0, почти невозможно, даже написав очень простой специализированный код.
      Другой вопрос, что IPC далеко не всегда показывает загрузку процессора. Например, эта метрика не знает, насколько полезные инструкции выполняются (может многие из этих инструкций — это работа с индексами), она никак не учитывает использование векторых операций, которые могут повысить производительность в 4-8 раз.
      Если интересна тема, рекомендую хороший сайт http://www.agner.org, там человек много экспериментирует и приводит эмпирические оценки с соображения для многих скрытых деталей.
      Цитата автора сайта по теме:

      I think the decoding front end and the renamer are designed with a 4-wide pipeline for a throughput of four µops per clock. These µops are queuing up in the reservation station if execution of them is delayed for any reason. The scheduler can issue more than 4 µops per clock cycle in bursts until the queue is empty.


      1. Igor_O
        23.05.2017 11:31

        Цитата автора сайта по теме:
        I think

        Забавно, но на «хоботе» лежит статья, сравнивающая архитектуру Санди Бридж с Хасвелом, там как раз подробно этот момент разобран. И да, официально — 4 декодера (3 «простых», выдающих одну микрокоманду, и один «сложный», выдающий до 4 х микрокоманд) из которых микрокоманды попадают в кэш на 56 микрокоманд, откуда попадают в буфер пересортировки.
        Хорошая, кстати, статья, хоть и трехлетней давности. Рекомендую: Достойна ли архитектура Haswell называться новой и переработанной?


  1. VaalKIA
    22.05.2017 20:48

    Поддерживаю комментаторов: чем измерять под Windows IPC, да ещё и на процессорах AMD?


    1. splav_asv
      23.05.2017 00:03
      +1

      Есть бесплатный пакет Amd codexl, содержащий в том числе профилировщик. Не совсем на уровне Intel vtune, но для многих задач достаточно.


  1. aamonster
    22.05.2017 21:26

    А что, кто-то оценивает cpu cache misses в целом, а не только для своей программы? (кстати, кто тут спрашивал — вроде инструменты для этого есть в профайлере Visual Studio)


    И если да — есть ли хоть какие-то методы с этим бороться глобально, а не просто исправляя свой код?


    1. VolCh
      23.05.2017 05:13

      Купить процесс с бОльшим кэшем. Некоторые модели по сути только размером кэша и отличаются.


      1. aamonster
        23.05.2017 08:47

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


        Я имел в виду методы оптимизации вроде "изолировать источники cache misses на одном ядре, чтоб не мешали остальным" (если это поможет).


  1. ToSHiC
    23.05.2017 00:01

    Вообще, кажется, что правильно было бы смотреть на stalled-cycles-frontend и stalled-cycles-backend, которые у вас помечены как . perf был запущен в системе в виртуалке, да?

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


  1. alan008
    23.05.2017 00:10

    Уважаемый автор, если не секрет, что за вычисления вы столь тщательно оптимизируете? Уровень между процессором и оперативкой в реальных приложениях вроде никогда не был узким местом. Чаще все упиралось либо в диск, либо в сеть, либо в синхронизацию потоков (в разделяемые структуры данных многопоточного приложения).


    1. DaylightIsBurning
      23.05.2017 00:30
      +4

      очень многие вещи упираются в оперативку. Например, если вам нужно перемножить поэлементно две больших матрицы — это memory-bound operation. Операции, которые связанны с random access — тоже часто memory bound, поэтому unordered_map, выполненный как дерево обычно намного медленнее чем dense_map.


    1. DaylightIsBurning
      23.05.2017 00:40
      +1

      Самая быстрая память 60GB/s, но это если копируются большие блоки целиком. Если копируются переменные размером по 4 байта, случайно разбросанные по памяти — будет намного хуже. При этом процессор может выполнять до 16 8-байтных операций за такт. Если операция — сложение двух переменных по 8 байт, выходит что процессор может перемолоть (8+8)*16*4Ghz=1.02400 TBps. В данном сценарии разрыв выходит более чем на порядок. В реальности он может быть ещё хуже, но, конечно, может быть и наоборот.


    1. aamonster
      23.05.2017 09:55
      +1

      Э… Вообще-то это совершенно стандартная проблема со времён 386. Классический пример тех времён — берём картинку и начинаем вращать её на экране (в те времена это делалось софтово). При использовании наивного алгоритма (отрисовка по строкам) — вращение быстрое, когда картинка повёрнута примерно "как была", и тормозится при повороте ближе к 90 градусам. Решалось отрисовкой по квадратикам 8*8 пикселей.


      В любом руководстве по оптимизации это описано, все давно умеют с этим бороться.


    1. tangro
      23.05.2017 11:25
      +1

      Банальное кодирование\декодирование 4к видео в 60 FPS легко может потребовать гонять десяток гигабайт в секунду туда-сюда. А такое видео нынче уже даже на ютюбе попадается.


  1. Loginin
    23.05.2017 11:05
    +4

    Выводы статьи кажутся странными.
    1. IPC не может точно указывать во что упёрлась программа — есть разные причины простоя и на разветвлённом плохо предсказываемом коде можно получить IPC < 1 даже имея все данные в кэше. Низкий IPC указывает на архитектурные простои любой природы (неверная спекуляция, нехватка ресурсов, задержки в доставке операндов и т.п.).

    2. На IPC не имеет смысла смотреть пока нет уверенности, что программа достаточно хорошо оптимизирована — на ранних этапах оптимизации макро-эффекты (неэффективные последовательности инструкций в силу неудачного алгоритма, размещения данных или кодирования) имеют гораздо больший эффект. Более удачная организация алгоритма и структур данных может дать как сокращение числа инструкций, так и снижение нагрузки на память (за счёт более эффективного кэширования) и может повлиять на IPC в любую сторону. Основной метрикой при оптимизации должны быть попугаи специфичные для приложения, а IPC лишь вспомогательный инструмент не очень полезный сам по себе (см.3).

    3. Не все IPC одинаково полезны — в AVX2 одна F32 инструкция FMA делает 16 операций, но в IPC она учтётся как одна инструкция. Цикл её заменяющий запросто может дать более высокий IPC, но FLOPS (попугаи приложения Linpack) от него будет гораздо меньше. Да и в более простом примере movl (%rax), %rbx, add %rbx, %rdx — это 2 инструкции, а add (%rax), %rdx — одна, но более высокий IPC для первого случая (скорее всего время выполнения для обоих случаев будет одинаковым, но инструкций в первом случае больше) не транслируется в более высокую производительность.

    Оптимизация на уровне IPC всегда должна делаться с оглядкой на исполняемый код (ну может кроме случая, когда цель — это повысить температуру в помещении за счёт загрузки процессора).


  1. vitaliy2
    23.05.2017 11:05

    Думаю, нужно отметить, что на картинке «А на самом деле это выглядит вот так» подразумевается, что количество виртуальных ядер равно количеству физических, и кроме памяти нет никаких других shared-ресурсов.

    К примеру, если система репортит 90% при 2 потоках на ядро, то на самом деле это порядка 99% нагрузки (полезная + холостая). И это при том, что нет никаких других shared-ресурсов. А они есть (но правда их может частично компенсировать SMI, уменьшая отношение холостой к полезной работе). Как-то так. В общем как минимум всё сложнее, чем на картинке.


  1. Roman_Cherkasov
    23.05.2017 11:05

    Уважаемые, а есть ли подобные(tiptop) инструменты для семейства Windows? Очень интересно было бы посмотреть на данные от видеоигр. А то по YouTube со стародавних времён гуляет холивар по поводу разгона FX 8xxx серии. Люди на 2 лагеря разделились, одни считают что стоит разгонять RAM, а другие считают что разгона ядер достаточно. Думаю что подобный инструмент разрешил бы часть споров по этому поводу.


    1. DustCn
      23.05.2017 12:48

      Тут надо не в IPC смотреть, а профилировать с учетом сколько меморийного бандвизя у вас остается после разгона ядер, если вы считаете что в РАМ уперлось.


  1. DustCn
    23.05.2017 12:39
    -1

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

    Это больно слышать для компаний, выпускающих процессоры.
    Чем выше IPC тем лучше процессор справляется с выполнением команд, тем лучше компилятор их сгенерировал. А вы говорите что это плохо. Окститесь!

    Дальше идет какой то пиздец, который я даже не буду тут приводить.
    Приложения бывают разные — синие, зеленые и красные. Есть понятие локальности данных, для разных алгоритмов она разная. Низкий IPC для кода с высокой локальностью данных — показатель говнокода. Пример — если у вас IPC 1.0 на перемножении матриц, значит что то пошло не так.
    С другой стороны приложения с низкой локальностью — спарс матрицы например, да еще и неупакованные — то все, приложение висит на латентности памяти, и высокий IPC там не достижим.

    Называть же IPC показателем платформы — это мягко говоря странно. У CPU есть свой предельный IPC определяющийся тем, сколько у него независимых портов на исполнение. Но это оценка сверху, выше которой уже не прыгнуть.

    Короче высокий IPC — это хорошо!


  1. madkite
    23.05.2017 16:59

    Если у вас IPC < 1.0, то я вас поздравляю, ваше приложение простаивает в ожидании данных от оперативной памяти.

    А разве все инструкции выполняются за один такт? Разве не существует инструкций которые выполняются несколько таков и т.о. даже при отсутствии ожидания среднее количество инструкций на такт будет меньше 1?


    1. Loginin
      23.05.2017 18:03
      +1

      Из-за конвейерного исполнения темп поступления/завершения инструкций (throughput) может быть выше чем скорость их исполнения (latency). БОльшая часть инструкций в современных процессорах может стартовать/завершаться с темпом одна инструкция за такт на порт и именно количество завершенных инструкций показывает IPC. Но есть и медленные инструкции, которые не могут стартовать каждый такт на одном порту, а также бывает, что внутреннего параллелизма вычислений не хватает для загрузки конвейера (свежие инструкции ждут результатов от исполняющихся). Тогда длительность исполнения инструкций начинает играть роль и IPC закономерно падает.


      1. f1inx
        24.05.2017 11:59

        Поправляю опечатку, на всякий случай, latency — это задержка (время) выполнения инструкции (и вообще чего либо) а не скорость.


        1. Loginin
          24.05.2017 18:50

          Ну да, неточно выразился, спасибо. latency для инструкции — это время её исполнения от постановки на исполнение до выработки результата.