← Все записи

Почему мой первый бенчмарк CPU был слишком шумным и как я это исправил

5 ноября 2026 г.

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

Все числа взяты из README репозитория cpu-inference-bench (включая раздел «First attempt (archived)») и из results/archive_summary.json.

Первая попытка оказалась непригодной

Я начал с запуска ResNet-18 на PyTorch, ONNX Runtime и OpenVINO с настройками по умолчанию на ноутбучном CPU (Intel i7-12650H). Чтобы проверить повторяемость, я запускал каждую конфигурацию дважды. У 12 из 18 повторных строк два одинаковых запуска отличались более чем на 5%, а для одной строки (PyTorch, 12 потоков, batch 1) — до 48,27%. Результаты нельзя было использовать для сравнения, поэтому я их заархивировал.

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

Поиск причины

В первой попытке использовалось масштабирование частоты по умолчанию, поэтому частота могла свободно меняться. У этого CPU устойчивое ограничение мощности пакета 45 Вт и кратковременное 115 Вт; такие ограничения по мощности и температуре могут менять частоту во время запуска. Фоновые службы и другие процессы на тех же ядрах тоже могут добавлять шум.

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

Пилот, которого всё ещё было недостаточно

Я ограничил P-ядра частотой 3000 МГц и провёл небольшой пилот. В двух из четырёх строк счётчики термического троттлинга ядра всё равно выросли, поэтому я выбрал 2600 МГц — частоту, которую ядра могут выдерживать.

Что я изменил

Все приведённые запуски используют:

  • фиксированную частоту 2600 МГц на 6 P-ядрах при отключённых SMT-соседях — устойчивую частоту, которую ядра могут удерживать, а не пиковую;
  • закреплённые ядра, питание от сети и остановленные фоновые службы;
  • ожидание охлаждения перед каждым повтором, пока температура пакета не станет ниже 60 °C;
  • чередующиеся раунды, чтобы дрейф одинаково влиял на все фреймворки;
  • правило стабильности: строка стабильна, только если разброс по 5 повторам ниже 5% и ни один счётчик термического троттлинга не вырос.

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

Что это дало

При таких ограничениях INT8 против FP32 для ResNet-18 при batch 1 дал 2,34× (PyTorch), 2,74× (ONNX Runtime) и 3,48× (OpenVINO, 2,6 мс). Пять из 36 строк BERT и 2 из 18 строк ResNet (обе — FP32) всё равно остались нестабильными, и в README об этом сказано.

Чего это не показывает

Тепловые счётчики не обнаруживают троттлинг по ограничению мощности, поэтому я также проверил столбцы с частотами. Во время всех запусков работал VPN-клиент, и я не измерял его влияние. Это один ноутбук и одна серия замеров.

Что я из этого вынес

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

Код написан с помощью Claude Code; методология, решения и проверка — мои.