Подтвердить что ты не робот

Ресурсы для понимания производительности С++?

Я ищу ресурсы (в идеале книгу), которые помогут мне получить глубокое понимание производительности С++. Здесь немного больше фона:

Я пишу серверное программное обеспечение с очень высокими требованиями к пропускной способности и/или с низкой задержкой. Мы пишем в С++; в настоящее время это не совсем для обсуждения. Большинство моих коллег, похоже, гораздо лучше понимают производительность С++. У них лучшие ментальные модели, поэтому они могут сказать, что некоторая часть кода будет плохо работать в масштабе. Мне не хватает этого понимания, и поэтому я хочу улучшить свою ментальную модель.

Меня особенно интересует:

  • Понимание эффектов кеша и то, как локальность кэша из-за макета объекта влияет на производительность моего кода. Это проблема номер один, которая, похоже, воспитывается другими членами моей команды.
  • Понимание того, как распределение памяти влияет на производительность. Должен ли я использовать TCMalloc (или другие mallocs) и как я должен знать? Как мне настроить различные параметры распределения и освобождения?
  • Как я узнаю, когда накладные расходы от копирования объектов будут иметь значение (и, следовательно, должны переключаться на указатели, например)?
  • Меня обычно интересуют "оптимизации", если у меня есть информация о том, когда их использовать.

Вещи, которые меня не интересуют:

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

В качестве отправной точки, кто-нибудь знает, соответствует ли эта книга Efficient С++ счету?

4b9b3361

Ответ 1

Позвольте мне разделить мои рекомендации на несколько разделов.

Оптимизация С++

В качестве отправной точки я бы настоятельно рекомендовал Agner Fog Оптимизация программного обеспечения на С++. Это руководство дает отличный обзор общих тем оптимизации С++.

Общие сведения об оборудовании в целом

Чтобы иметь хорошую ментальную модель производительности С++, вам также необходимо понять базовое оборудование. Рассмотрим это утверждение:

a[7] = 5;

На стороне языка С++ строка кода скучна с точки зрения производительности: это всего лишь одна запись в памяти. Но на реальном оборудовании производительность записи в памяти может меняться на порядок. Чтобы понять, что происходит на этом уровне, вам нужно узнать о таких понятиях, как кеши, конвейер процессора, TLB, предсказание ветвей и т.д.

В качестве краткого введения в кэши процессора я бы рекомендовал статью Галерея эффектов кэша процессора. Более глубокое и продолжительное ( > 100 страниц) обсуждение кэшей и компьютерной памяти Что должен знать каждый программист о памяти.

Чтобы получить общее представление о современном компьютерном оборудовании, компьютерная архитектура: количественный подход - рекомендуемая книга. Я сам не читал книгу, а учился, читая блоги и эксперименты. Однако, по-видимому, другие считают книгу очень полезной.

Общие сведения о конкретных процессорах

В какой-то момент вашего путешествия, чтобы улучшить свои навыки оптимизации, вам будет полезно узнать особенности разных процессоров. В качестве одного из многих примеров разные процессоры Intel и AMD имеют очень разные штрафы за использование невыровненных инструкций SSE, например, встроенный в _mm_storeu_ps С++.

Чтобы узнать особенности разных процессоров, я бы рекомендовал Микроархитектура процессоров Intel, AMD и VIA: руководство по оптимизации для программистов-сборщиков и разработчиков компиляторов. Фактически, я просто собираюсь продолжить и рекомендовать все руководства по оптимизации от Agner Fog. Кроме того, поставщики оборудования предоставляют документацию для своего конкретного оборудования.

Обучение использованию инструментов

Хорошая ментальная модель С++ и аппаратная производительность очень полезны при оптимизации кода. Но научиться использовать нужные инструменты по крайней мере так же полезно. Вероятно, лучшим советом для оптимизации является "Сначала измерьте!". Чрезвычайно сложно понять производительность даже простого блока кода, просто подумав об этом. Вы получите много информации, запустив код и измерив его различными способами.

Вот некоторые из полезных полезных измерений:

  • Сроки: просто запустите код и измерьте время
  • Пробоотборники пробоотбора
  • Инструментальные профилировщики
  • Счетчики процессоров

Я не буду давать рекомендации по конкретным инструментам, так как я, возможно, выхожу из сферы вашего первоначального вопроса. И инструменты - это большая тема: инструменты различаются для разных аппаратных платформ, программных платформ и стоимости (некоторые из них бесплатны, некоторые из них дороги).

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

Ответ 2

Valgrind должен быть вашим первым инструментом.

У Valgrind есть много инструментов, но cachegrind - отличный способ узнать, имеет ли ваш алгоритм хорошую локальность данных. Это выявит узкие места в памяти. Callgrind - еще один модуль valgrind, который поможет вам определить узкие места в обработке.

Литература:

похожего на Cachegrind: http://valgrind.org/docs/manual/cg-manual.html

Callgrind: http://valgrind.org/docs/manual/cl-manual.html

Ответ 3

Предыдущие ответы дали самые важные мысли.

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

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

Использование STL и BOOST, вероятно, поможет избежать некоторых ошибок.

Ответ 4

Чтобы понять, что происходит на этом уровне, вам нужно узнать о таких понятиях, как кеши, конвейер процессора, TLB, предсказание ветвей и т.д.

Я хотел бы обсудить это дальше в очень случайной манере.

  • Кэш. В принципе, если вы можете попытаться подогнать свой рабочий набор внутри кеша, ваше приложение может видеть прирост скорости огромной.
  • Филиалы - Филиалы берут ОЧЕНЬ долгое время, потому что им нужен блок для чтения в памяти. Например, x=1 может быть быстрее, чем if (needWrite) x=1;, даже если вы делаете ненужные записи.
  • предсказание ветки - из-за предыдущего процессор пытается попытаться "угадать", что результат ветки использует алгоритмы сопоставления шаблонов. Предоставление этого треугольника, чтобы угадать, может дать вам прирост скорости.
  • Что касается процессорных конвейеров, уровня инструкций Parallelism, суперскаляр, переименования регистров и других - это, по-моему, должно быть оптимизировано компилятором.