Комментарии 62
Естественный показатель — это шум от вентиляторов. Добавить датчик шума, откалибровать — и абсолютно точный результат. Кроме процессоров типа i7-7700k, конечно.
Может, лучше электросчётчик?
Зато вентиляторы можно распознавать на слух без дополнительных устройств.
Зато когда что-нибудь ночью считается или рендерится, пока спишь, сразу просыпаешься, как только уровень шума уменьшился…
Энергопотребление чего? Матплаты, памяти, видеокарты, дисков?
А как его замерить?
С другой стороны, есть готовые тулзы у MS и у Intel, которые как-то оценивают энергопотребление процессора «в реальном времени».
![](https://habrastorage.org/web/f74/762/998/f74762998aae4f3690ddd1eaed2b576d.png)
Хотя, вроде как на некоторых серверных платформах есть способ непосредственно через мониторинг смотреть энергопотребление процессора.
(но когда я однажды участвовал в разработке 4-х процессорной платы, у нас, кажется, мониторинг энергопотребления процессоров предусмотрен не был...)
на этом процессоре максимально возможным значением IPC могло бы быть 4.0 (это связано со способом получения и выполнения инструкций современными процессорами).
…
Если у вас IPC > 1.0, то ваше приложение страдает не столько от ожидания данных, сколько от чрезмерного количества выполняемых инструкций.
…
Как вы видите, я провёл черту по значению IPC равному 1.0.
Непонятно, почему бы не загрузить суперскалярный процессор на полную, раз он умеет выполнять больше одной инструкции за такт? В конце концов, программы (по крайней мере некоторые) выполняют вычисления, а не просто гоняют данные в памяти.
P.S. "IPC — instructions per cycle": Мне казалось, понятия "цикл" и "такт" означают разное.
Мне казалось, понятия «цикл» и «такт» означают разное.
Русская Википедия не имеет перевода статьи Instruction cycle. Люди на StackExange говорят, что правильнее «такт».
Мне казалось, понятия «цикл» и «такт» означают разное
Очень зависит от переводчика и контекста. В заграничном языке частота процессора называется «clock speed», т.е. скорость часов. Соответственно, меряется в «оборотах (которые не rotation, а cycle) в секунду». Различие между циклами и тактами, теоретически, может возникнуть на стыке цифры и аналога, где на один цикл синусоиды может приходиться несколько отсчетов… Но живьем такого никогда не встречал.
В общем случае «цикл процессора» и «такт процессора» — синонимы.
Непонятно, почему бы не загрузить суперскалярный процессор...
Загрузить суперскалярный процессор «на полную» можно только специально подобранным набором инструкций без ветвлений, переходов и обращений в память. 4 инструкции за такт возникают за счет конвейеров и того факта, что после загрузки команды в конвейер, уже на следующем такте туда можно грузить следующую инструкцию (условно, примерно, не совсем так, но...). Но, конвейер имеет глубину для, например, современных интелов, больше 20 команд. Следовательно, любой «промах» в предсказании ветвления означает, что у нас значительная часть команд, которые успели загрузиться в конвейер, нужно выкинуть и начать грузить конвейер по-новой командами из другой ветки. Опять же, сейчас оно не прямо вот совсем так устроено, принимаются меры для борьбы и куча страшных аббревиатур: распараллеливание декодирования команд, распараллеливание выполнения микрокоманд, переупорядочивание микрокоманд, чтобы максимальное количество выполнялось параллельно и т.д.
Насколько я понимаю, автор утверждает, что "максимальное количество команд выполнялось бы параллельно" — это плохо, и это кажется мне странным. Если конвейер работает с максимальной производительностью, например перемножая небольшие вектора или матрицы 4х4, то что, вычисления нужно разбавлять доступами в память, чтобы обеспечить IPC=1 ?
«процессор Шрёдингера»
На сколько я помню, что-то такое пробовали делать. Но, сильно широко не применяется. Даже один из самых ранних алгоритмов предсказания ветвлений от IBM «попадал» больше, чем в 90% случаев, а некоторые из современных алгоритмов в некоторых задачах «угадывают» больше 97% ветвлений.
Да, хотелось бы тоже измерить
В моменты времени когда может осуществляться принудительное переключение контекста задачи (т.е. 1 раз за JIFFY) происходит инкремент в структуре task активных в данный момент задач их load_time. Поэтому если по каким либо причинам переключение задач окрашено данная статистика может «безбожно» врать. Т.е. мы, например, можем сделать искусственный процесс, который будет на 100% загружать ресурсы CPU четко между JIFFY затем переключаться в режиме I/O SHCHEDUILIG на короткое время на другой процесс и результатом будет 0% загрузка по данным TOP.
Проблема производительности это скорее IPC не близко к максимально возможному для данной архитектуры CPU.
Конечно для окончательного вывода требуется более комплексный анализ алгоритма, оптимальности загрузки внешних шин, кэшей, page faults, branch miss predictions, interrupt rate, trap/exception/taskswitch/cpu migration rate.
Есть куча инструкций которые выполняются больше чем один такт и не позволяют их выполнять параллельно с другими.
Простите за нубский вопрос — а как определить максимум для своего процессора?
Но это такие «рафинированные» цифры, которые никак не учитывают 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.
Цитата автора сайта по теме:
I think
Забавно, но на «хоботе» лежит статья, сравнивающая архитектуру Санди Бридж с Хасвелом, там как раз подробно этот момент разобран. И да, официально — 4 декодера (3 «простых», выдающих одну микрокоманду, и один «сложный», выдающий до 4 х микрокоманд) из которых микрокоманды попадают в кэш на 56 микрокоманд, откуда попадают в буфер пересортировки.
Хорошая, кстати, статья, хоть и трехлетней давности. Рекомендую: Достойна ли архитектура Haswell называться новой и переработанной?
А что, кто-то оценивает cpu cache misses в целом, а не только для своей программы? (кстати, кто тут спрашивал — вроде инструменты для этого есть в профайлере Visual Studio)
И если да — есть ли хоть какие-то методы с этим бороться глобально, а не просто исправляя свой код?
Купить процесс с бОльшим кэшем. Некоторые модели по сути только размером кэша и отличаются.
Это понятно, но в большинстве случаев не поможет (если алгоритм "гуляет по памяти" — обычно у него в активном использовании действительно большой объём), а покупать проц только для того, чтобы проверить — дорогое удовольствие (метрик же, позволяющих оценить, какой размер кэша спасёт отца русской демократии, вроде нету).
Я имел в виду методы оптимизации вроде "изолировать источники cache misses на одном ядре, чтоб не мешали остальным" (если это поможет).
Во вторых, программа, которая постоянно прогружает все исполнительные блоки — это довольно редкое явление, если это, конечно, не бенчмарк. Более того, в современном мире устройств, работающих от батареи, важнее, сколько электричества будет использовано для работы программы, и далеко не факт, что наилучшая энергоэффективность и максимально возможное значение IPC — это одна и та же точка.
Уважаемый автор, если не секрет, что за вычисления вы столь тщательно оптимизируете? Уровень между процессором и оперативкой в реальных приложениях вроде никогда не был узким местом. Чаще все упиралось либо в диск, либо в сеть, либо в синхронизацию потоков (в разделяемые структуры данных многопоточного приложения).
Э… Вообще-то это совершенно стандартная проблема со времён 386. Классический пример тех времён — берём картинку и начинаем вращать её на экране (в те времена это делалось софтово). При использовании наивного алгоритма (отрисовка по строкам) — вращение быстрое, когда картинка повёрнута примерно "как была", и тормозится при повороте ближе к 90 градусам. Решалось отрисовкой по квадратикам 8*8 пикселей.
В любом руководстве по оптимизации это описано, все давно умеют с этим бороться.
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 всегда должна делаться с оглядкой на исполняемый код (ну может кроме случая, когда цель — это повысить температуру в помещении за счёт загрузки процессора).
К примеру, если система репортит 90% при 2 потоках на ядро, то на самом деле это порядка 99% нагрузки (полезная + холостая). И это при том, что нет никаких других shared-ресурсов. А они есть (но правда их может частично компенсировать SMI, уменьшая отношение холостой к полезной работе). Как-то так. В общем как минимум всё сложнее, чем на картинке.
Это больно слышать для компаний, выпускающих процессоры.
Чем выше IPC тем лучше процессор справляется с выполнением команд, тем лучше компилятор их сгенерировал. А вы говорите что это плохо. Окститесь!
Дальше идет какой то пи**ец, который я даже не буду тут приводить.
Приложения бывают разные — синие, зеленые и красные. Есть понятие локальности данных, для разных алгоритмов она разная. Низкий IPC для кода с высокой локальностью данных — показатель говнокода. Пример — если у вас IPC 1.0 на перемножении матриц, значит что то пошло не так.
С другой стороны приложения с низкой локальностью — спарс матрицы например, да еще и неупакованные — то все, приложение висит на латентности памяти, и высокий IPC там не достижим.
Называть же IPC показателем платформы — это мягко говоря странно. У CPU есть свой предельный IPC определяющийся тем, сколько у него независимых портов на исполнение. Но это оценка сверху, выше которой уже не прыгнуть.
Короче высокий IPC — это хорошо!
Если у вас IPC < 1.0, то я вас поздравляю, ваше приложение простаивает в ожидании данных от оперативной памяти.
А разве все инструкции выполняются за один такт? Разве не существует инструкций которые выполняются несколько таков и т.о. даже при отсутствии ожидания среднее количество инструкций на такт будет меньше 1?
Вы неверно измеряете загрузку процессора