Когда чрезмерное увеличение размера кода начинает иметь значимый эффект на производительность?

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

Да, это - крошечный проект, и на самом деле даже если мой исполняемый файл чрезмерно увеличивает размер 10 x его размер, это все еще будет приблизительно 5 МБ, который едва кажется большим по сегодняшним стандартам... или является этим? Это приносит мне к моему вопросу. Действительно ли скорость пропорциональна размеру или является там прыжками и плато в определенных порогах, порогами, которые я должен стремиться оставаться ниже? (И если так, каковы пороги конкретно?)

10
задан skaffman 23 March 2012 в 10:54
поделиться

10 ответов

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

«Дизайн, ориентированный на данные» помогает с локализацией кода и данных, по моему опыту. Возможно, вас заинтересуют слайды Ловушки объектно-ориентированного программирования (pdf) ( зеркально отражены здесь (pdf) ), которые хорошо демонстрируют, как решать проблемы таким образом. что вы получаете как хорошие данные, так и локальность кода.

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

15
ответ дан 3 December 2019 в 13:40
поделиться

"Раздутость" исполняемого файла меньше влияет на производительность, чем следующие два фактора (которые связаны, но не одинаковы)

  1. Размер рабочего набора кода.
  2. Размер рабочего набора данных.

Объем кода, который ваша программа должна выполнить для выполнения единицы работы, например, рендеринга кадра, влияет на частоту попадания в кэш инструкций и частоту попадания в таблицу страниц. Однако, если 90% работы выполняется одной небольшой функцией, которая полностью помещается в i-cache, то размер кода программы в целом будет учитывать только остальные 10%.

Аналогично с данными, если ваша программа должна обрабатывать 100 МБ данных каждый кадр, она будет работать намного хуже, чем программа с рабочим набором, который помещается в кэш L1, L2 или L3.

Так что дело не в том, насколько велик исполняемый файл, а в том, сколько "материала" используется в каждый момент времени.

6
ответ дан 3 December 2019 в 13:40
поделиться

На практике общее выполнение обычно зависит от алгоритмов, которые вы используете.

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

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

1
ответ дан 3 December 2019 в 13:40
поделиться

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

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

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

-1
ответ дан 3 December 2019 в 13:40
поделиться

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

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

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

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

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

10
ответ дан 3 December 2019 в 13:40
поделиться

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

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

4
ответ дан 3 December 2019 в 13:40
поделиться

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

Вызов выглядит примерно так valgrind --tool=cachegrind ./ваша_программа аргументы.

Существует также хороший Qt GUI для набора valgrind под названием KCacheGrind.

3
ответ дан 3 December 2019 в 13:40
поделиться

Я не заметил большой корреляции между размером моих проектов OpenGL и производительностью, однако я никогда не брался за большой проект. Написание эффективного кода - вот что важнее. Что ты пытаешься сделать? Насколько важен дополнительный прирост производительности для вашего приложения? Сосредоточьтесь на написании хорошего кода, и все будет в порядке. Обязательно попробуйте шаблоны в качестве полезного опыта, регулярно коммитируйте, чтобы всегда можно было вернуться.

1
ответ дан 3 December 2019 в 13:40
поделиться

По моему опыту, раздувание кода и раздувание времени выполнения идут рука об руку, и все дело в том, как разработано программное обеспечение, в частности, как разработана структура данных.

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

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

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

2
ответ дан 3 December 2019 в 13:40
поделиться

Размер вашего исполняемого файла не имеет значения. Имеет значение размер «активного» кода, кода, который на самом деле часто выполняется приложением. К сожалению, это намного сложнее выразить количественно. Для простого приближения вы можете профилировать свое приложение, взять процедуры, на которые приходится 90% времени выполнения, и сложить их размеры кода.

Большинство современных процессоров имеют кеш-память инструкций размером 64 или 128 КБ, поэтому это помогает сохранить активный код ниже этого размера. Следующим порогом будет размер L2, который может составлять несколько мегабайт.

2
ответ дан 3 December 2019 в 13:40
поделиться
Другие вопросы по тегам:

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