Почему я должен заботиться о микропроизводительности и эффективности?


71

Многие вопросы и ответы на страницах C / C ++, конкретно или косвенно обсуждают проблемы микро производительности (такие как издержки косвенной или прямой против встроенной функции), или использование алгоритма O (N 2 ) против O (N log N) на список из 100 предметов.

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

Мой вопрос: почему так много программистов так заботятся? Действительно ли это проблема для большинства разработчиков, мне просто повезло, что мне не пришлось об этом слишком беспокоиться, или я плохой программист?


5
+1, хороший общий вопрос.
Iammilind

+1 хороший вопрос .. я добавил 2 тега .. надеюсь, вы не против этого.

2
Я возглавляю две великие цитаты 1) «Преждевременная оптимизация - корень всего зла». 2) 80% вашего времени будет потрачено на 20% вашего кода (правило 80/20).
Джеймс Хури

2
Я заметил пару ответов, рассказывающих о моем примере O (n * n). Я явно указал список из 100 элементов, но они все еще настаивают на том, что O (nlogn) лучше, явно заявляя об улучшении производительности, если список, в дальнейшем, достигнет 1000 или миллионов. Является ли это навязчивой идеей микрооптимизации, потому что программисты программируют на возможные будущие требования, а не на текущие текущие требования? (Где я слышал это раньше ...)
Mattnz

5
@ Джеймс полностью цитирует Дональда Кнута: «Мы должны забыть о малой эффективности, скажем, в 97% случаев: преждевременная оптимизация - корень всего зла». Там будет несколько хороших ответов о оставшихся 3% в этой теме.
StuperUser

Ответы:


14

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

Одна из самых простых ловушек - особенно в C и C ++, где у вас есть такой детальный контроль - оптимизация выполняется слишком рано и на слишком хорошем уровне. В общем случае правило таково: A) не оптимизируйте, пока не обнаружите, что у вас есть проблема, и B) не оптимизируйте ничего, с чем вы не столкнулись с проблемной областью, с помощью профилировщика.

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


6
Еще один: код инициализации, который выполняется один раз, обычно не нуждается в оптимизации, так что смотрите в другом месте.
Майк ДеСимон,

3
Зависит от того, как часто «один раз». Во время работы ./configureя бы сказал, что до 75% времени выполнения может быть потрачено на «инициализацию» кода в программах, которые запускает скрипт. 25-50% могут быть потрачены на динамические ссылки.
R ..

12
Правило А это ужасное правило. Архитектура системы играет важную роль в производительности, и если вы узнаете позже, ваша архитектура просто не сможет удовлетворить ваши требования к производительности, вы в основном облажались. Таким образом, хотя вы можете пропустить мелкие детали, полностью игнорировать это в начале просто неправильно.
edA-qa mort-ora-y

3
@ edA-qa: Раньше я так думал, но за многие годы многие проекты потерпели неудачу или потерпели неудачу, прежде чем какие-либо соображения производительности стали вызывать озабоченность. Каждый раз, когда у меня возникали проблемы с производительностью, исправление было сравнительно дешевым, дни или несколько недель. Не больше беспокойства, чем любая другая «ошибка», обнаруженная в процессе разработки. Однако, как и любой другой элемент риска, показатели производительности должны быть определены и снижены в начале проекта.
Mattnz

5
ФП спросил, почему так много забот, и я не вижу, как этот ответ на самом деле ответил на вопрос, если ФП больше не заинтересован в том, чтобы кто-то сказал: «Не беспокойтесь об этом!».
красная грязь

54

Я думаю, что все в вашем списке - это микрооптимизация, на которую вообще не следует смотреть, кроме

использование алгоритма O (n * n) против O (NlogN) в списке из 100 элементов

на который я думаю стоит посмотреть. Конечно, сейчас этот список состоит из 100 пунктов, и все быстро для маленьких n , но я бы поспорил, что этот код будет многократно использоваться для списка из нескольких миллионов строк, и код все еще будет иметь работать разумно.

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


36
+1 за «Выбор правильного алгоритма никогда не бывает микрооптимизацией».

9
Я тоже добавил +1, но учтите, что выбор оптимального алгоритма big-O, когда размеры данных обязательно будут небольшими, может отрицательно сказаться на времени разработки, размере программы и, возможно, даже использовании памяти. Если вы сортируете покерные руки, вы действительно хотите написать быструю сортировку, сглаживание или слияние? Я хотел бы начать с простой сортировки вставки или использовать сеть сортировки.
R ..

8
Забавно. В теме о микрооптимизации многие комментаторы микрооптимизируют ответы. ;)
Безопасный

5
«Я был бы готов поспорить, что этот код будет повторно использован для списка из нескольких миллионов строк»: это полностью зависит от проблемной области. Примеры: если вы пишете шахматный алгоритм, вы можете быть уверены, что размер доски не изменится. Если вы программируете автономное транспортное средство, количество колес не будет расти , что быстро, либо.
nikie

3
Мне не нравится «выбор правильного алгоритма никогда не является микрооптимизацией», потому что он ЯВНО верен, учитывая природу слова «правильно». Тем не менее, я чувствую, что ваш вывод - это действительно «самый быстрый или самый эффективный» алгоритм, с которым я не согласен. Выбор наиболее эффективного алгоритма - неправильный выбор, если для его реализации требуется много времени, а скорость или пространство этого сегмента практически не имеют значения.
Кейси Паттон

18

Давным-давно, на своей первой работе я написал код для встроенных систем. Эти системы использовали 8086 микропроцессоров и имели ограниченную память. Мы использовали компилятор Intel C. Одна система, которую я построил, была необходима для доступа к массиву трехмерных структур. Я построил его так, как мне сказала книга: вызовите malloc для трех измерений, затем выделите строки для следующего измерения, затем calloc для конечных узлов.

Это было довольно сложно (для меня в то время), мне пришлось делать подбор кривой, контроль процесса ANOVA и анализ хи-квадрат. Не было библиотек, которые сделали бы это для нас; мы должны были написать все это и установить все это на 8086.

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


В другом случае на той же работе клиент жаловался на время отклика в своей статистической системе управления процессом. Передо мной была разработана система «программного ПЛК», в которой операторы могли использовать логическую логику для объединения сигналов и отключающих переключателей. Они написали это на упрощенном языке, который мы сегодня называем «языком, специфичным для предметной области». насколько я помню это выглядело ((A1 + B1) > 4) AND (C1 > C2)и так далее.

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

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

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


Совсем недавно я работал над системой, которая должна была динамически анализировать поток XML. Большие файлы заняли бы значительно больше времени. Это было очень чувствительно к производительности; слишком медленный анализ может привести к тому, что пользовательский интерфейс станет полностью непригодным для использования.

Подобные вещи возникают постоянно.


Так что .... иногда вам нужен обслуживаемый, простой в написании код. Иногда вам нужен код, который выполняется быстро. Компромисс - это инженерное решение, которое вам нужно принять для каждого проекта.


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

6
@CodeInChaos: ответ не требует иного. Это говорит о том, что ОП "Почему я должен заботиться о производительности и эффективности микропроцессоров?" Вопросы до оптимизации были просто выведены другими ответчиками.
webbiedave

12

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


2
+1 - также высокочастотное финансирование, любой вид аудио / видео кодировщика / декодера, симуляции и моделирование (например, игры), общесистемные биты, такие как планировщики ЦП и диспетчеры памяти и т. Д.
Billy ONeal

3
МОЖЕТ быть критичным, но СЕЙЧАС критичным только после того, как вы докажете, что это так, и профилировали его так, чтобы оно было там, где вы думаете, что проблема. (Подсказка: это, вероятно, не там.)
ПРОСТО МОЕ правильное МНЕНИЕ

2
@ ПРОСТО МОЕ правильное МНЕНИЕ: фактически, для обработки изображений обработка данных обычно является вторым по величине потребителем времени (ввод-вывод все еще является самым большим). Тем не менее, оптимизация для ввода / вывода требует много необычных / сумасшедших проектов и их принятия коллегами-программистами, и иногда это просто невозможно улучшить. Обрабатывающая часть, однако, обычно смущающе распараллеливается, следовательно, они легко достижимы. (Одна настройка может рассматриваться другой как прямая реализация учебника ... если вы не достигнете уровня VirtualDub)
rwong

12

Позвольте мне рассказать вам немного о том, что стоит за культурой.

Если вам больше 40, чем 20, и вы программируете на жизнь в зрелом возрасте, то вы достигли совершеннолетия, когда C ++ была действительно единственной игрой в городе, настольные приложения были нормой, а аппаратное обеспечение все еще сильно отстает от программного обеспечения с точки зрения пропускной способности / производительности.

  • Раньше нам приходилось делать глупые трюки в программировании, чтобы иметь возможность читать большие (> 2G) файлы ...
  • Мы привыкли беспокоиться о размере исполняемого файла ...
  • Раньше мы беспокоились о том, сколько памяти потребляют наши программы ...
  • Мы регулярно принимали компромиссные решения времени и пространства ...
  • Даже на заднем плане нам приходилось писать CGI-программы на C или C ++ для чего-либо, чтобы справиться с приличным «нет». RPS ... Это было на несколько порядков быстрее.
  • Мы использовали для запуска тестов на достоинствах производительности между delphi / c ++ / vb!

Очень немногие люди должны беспокоиться об этих вещах сегодня.

Однако 10 лет назад вам по-прежнему приходилось беспокоиться о том, что ваше программное обеспечение загружается через модем 56 КБ и работает на 5-летнем ПК ... Помните ли вы, какие дрянные ПК были в 1996 году? Подумайте о 4 ГБ жесткого диска, 200 МГц процессоре и 128 МБ ОЗУ ...

А серверы 10 лет назад? Сервер Dell «следующего поколения» обошелся в 2000 долларов и имел 2 (!) Процессора Pentium 1 ГГц, 2 ГБ или Ram и жесткий диск 20 ГБ.

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


1
Дополнительный 20-летний опыт также означает, что мы получили ожоги от того, что прошли процесс оптимизации много-много раз, и избегаем того, что может понадобиться позже. По той же причине я не сильно бью себя по пальцу, когда использую молоток.
Blrfl

1
разматывание петли <дрожь>
красная грязь

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

9

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

преждевременная оптимизация, которая а) занимает намного больше времени, чем простое решение; б) вводит больше кода, в котором простое решение было бы вдвое меньше, а вдвое сложнее, и в) делает вещи менее читабельными, АБСОЛЮТНО следует избегать. Однако, если у разработчика есть выбор между использованием std :: map или std :: vector, и он выбирает неправильную коллекцию из чистого невежества для производительности, которая столь же плоха, если не хуже, чем преждевременная оптимизация. Что если бы вы могли немного изменить свой код сегодня, сохранить читабельность, сохранить ту же сложность, но сделать его более эффективным, сделаете ли вы это? Или вы бы назвали это «преждевременной оптимизацией»? Я нахожу, что многие люди даже не думают об этом так или иначе.

Когда-то я был парнем, который советовал «микрооптимизацию», которая требовала очень небольших изменений, и мне дали тот же ответ, который вы только что сказали: «Не стоит оптимизировать слишком рано. Давайте просто заставим это работать, и мы изменим его». позже, если есть проблемы с производительностью ". Прошло несколько релизов, прежде чем мы это исправили. И да, это была проблема с производительностью.

Хотя ранняя оптимизация может быть не очень хорошей, я думаю, что было бы очень полезно, если бы люди писали код с пониманием того, что собирается делать этот код, а не просто игнорировали любой вопрос, который приводит к обозначению O (x), как к «оптимизации». Сейчас вы можете написать много кода, и, не задумываясь о производительности, избегайте 80% проблем в будущем.

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

Итак, в заключение, всегда помня о производительности, вырабатывает хорошие привычки. Что так же важно, как писать чистый, как можно более простой и организованный код.


+1: это один из факторов трудоустройства для тех, кто нанят для разработки программного обеспечения Shrinkwrap и коммерческих веб-сайтов . Профилактика обходится дешевле, чем проклятие клиента.
Rwong

6

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

Тем не менее, несомненно, есть и преждевременная оптимизация. Правильно или нет, C и C ++ имеют репутацию производительности, которая привлекает людей, которые заботятся о производительности, включая тех, кто может оптимизировать столько же, сколько и получать удовольствие, потому что это действительно необходимо.


1
+1 - Примечание: большинство вопросов SO с тегом «performance», вероятно, являются частью этой ошибки выборки: P
Billy ONeal

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

4
Когда вы имеете дело с чем-то хитрым, часто кажется, что легче отдохнуть от сложной проблемы и тратить свое время на размышления о том, следует ли вам использовать i++или++i
Carson63000

@ Carson63000: да, это может полностью исказить образцы. Или они проводят время, отвечая на вопросы о том, почему мой operator ++не компилируется.
Rwong

4

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

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

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

Например, семейство микроконтроллеров STM32 работает с частотой 24 МГц, 16 КБ флэш-памяти и 4 КБ ОЗУ , до 120 МГц, 1 МБ флэш-памяти и 128 КБ ОЗУ .

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


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

2

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

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


+1: стоит отметить, что «патологические показатели» могут произойти с кем угодно в мире, независимо от языка или платформы. Возможность повторной реализации на языке более низкого уровня для тестирования и чтения дизассемблирования может дать больше информации , но не всегда обеспечивает работоспособное решение. Пример: «Я знаю, что могу сделать это в сборке - но он должен работать в среде с частичным доверием!»
Rwong

2

Производительность всегда актуальна, когда вы имеете дело с C и C ++. Что касается того, как далеко нужно идти, вы всегда можете сходить с ума до точки встроенного ASM или использовать арифметику указателей для более быстрой итерации. Однако наступает момент, когда человек тратит так много времени на оптимизацию, что работа над разработкой всей программы прекращается.

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

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

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


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

арифметика указателя не быстрее чем ж / д.

2

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

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

Тем не менее, метод, который я использую, похож на ваш, но не такой:

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

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

Вот пример того, что я имею в виду.


1

Честно говоря, это зависит от вашей цели и от того, занимаетесь ли вы профессиональным программированием или хобби.

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

Ранние программисты MIT не были рождены, чтобы делать потрясающие вещи; Они начали упрощать и усиливать существующие алгоритмы. Их гордость состояла в том, чтобы заставить 2 + 2 дать четыре за две секунды меньше, чем существующий алгоритм (это только пример, вы понимаете). Они постоянно пытались использовать меньше перфокарт в своих машинах TI-83 для повышения производительности.

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

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


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

Они этого не делают, но у них, безусловно, есть больше времени, чтобы работать над ними, просто если они этого хотят.

3
Я бы сказал обратное. У меня есть 8 или более часов в день, чтобы работать над чем-то, как профессионал. Я получаю 1, может быть, 2 часа в день для моих хобби проектов.
Билли ОНил

1

используя алгоритм O (N2) против O (NlogN) в списке из 100 элементов.

Я был в похожей ситуации недавно. У меня был массив предметов. В ожидаемом случае в списке было два (!) Элемента, и даже в худшем случае я не ожидал больше четырех или восьми.

Мне нужно было отсортировать этот список. Оказывается, замена std::sortна сортировочную сеть (по сути, много вложенных if) сократила большой процент времени работы (я не помню число, но это было что-то вроде 10–20%). Это огромное преимущество микрооптимизации, а код абсолютно критичен к производительности.

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


1

Совокупное использование энергии

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

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

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

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


[1] Я только что сделал это, 10 миллионов секунд 50 Вт. Точная цифра зависит от многих вещей.


1
Вы должны сразу начать с упоминания волшебного слова «мобильный». При работе на настольной платформе приложение, которое тратит 1/100 секунды процессорного времени на рисование кадра 60 раз в секунду, будет «достаточно быстрым»; улучшение производительности в десять раз не будет иметь никакого значения для пользователя. Однако на мобильной платформе приложение, которое работает с 90% загрузкой ЦП, может потреблять батареи гораздо быстрее, чем при 10%.
суперкат

1

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

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

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

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

Конечно, это другой случай, когда нужно говорить о необходимости оптимизации (и, что более важно, когда ее нет), микро или алгоритмической. Но в моем конкретном случае, если критический путь выполнения требует оптимизации, выигрыш в скорости 10x + часто достигается за счет оптимизаций на микроуровне, таких как многопоточность, SIMD и переупорядочение схем памяти и шаблонов доступа для улучшения местоположения ссылки. Я не так часто, скажем, заменяю пузырьковую сортировку на интросортную или радикальную сортировку или обнаружение столкновений квадратичной сложности с помощью BVH настолько, насколько нахожу горячие точки, которые, скажем, выигрывают от расщепления горячих / холодных полей.

Теперь в моем случае моя область настолько критична к производительности (трассировка лучей, физические движки и т. Д.), Что медленный, но совершенно правильный трассировщик лучей, для визуализации которого требуется 10 часов, часто считается бесполезным или более быстрым, полностью интерактивным, но выводит самые уродливые изображения с лучами, протекающими повсюду из-за отсутствия пересечения водонепроницаемых лучей / три. Скорость, возможно, является основной метрикой качества такого программного обеспечения, возможно, даже больше, чем корректность в какой-то момент (поскольку «правильность» - это нечеткая идея с трассировкой лучей, поскольку все приближается, пока оно не дает сбой или что-то в этом роде). И когда это так, если я не думаю об эффективности заранее, я нахожу, что мне действительно нужно изменить код на самом дорогом уровне проектирования, чтобы обрабатывать более эффективные проекты. Так что, если я не

Игры - это еще одно поле, похожее на мое. Неважно, насколько правильна ваша игровая логика или насколько удобна и блестяще спроектирована ваша кодовая база, если ваша игра работает со скоростью 1 кадр в секунду, как слайд-шоу. В некоторых областях отсутствие скорости может фактически сделать приложение бесполезным для его пользователей. В отличие от игр, в таких областях, как трассировка лучей, нет «достаточно хорошей» метрики. Пользователи всегда хотят большей скорости, а промышленная конкуренция состоит в основном в поиске более быстрых решений. Он никогда не будет достаточно хорош до реального времени, когда игры будут использовать трассировщики пути. И тогда это, вероятно, все еще не будет достаточно хорошо для VFX, с тех пор художники могли бы хотеть загружать миллиарды полигонов и имитировать частицы с самовоздействием среди миллиардов частиц при 30 + FPS.

Теперь, если это удобно, несмотря на это, я все еще пишу около 90% кода на языке сценариев (Lua), не заботясь о производительности. Но у меня есть необычайно большой объем кода, который действительно должен проходить через миллионы и миллиарды вещей, и когда вы перебираете миллионы и миллиарды вещей, вы начинаете замечать грандиозную разницу между наивным однопоточным кодом, который вызывает ошибку кэша при каждой итерации или, скажем, векторизованном коде, работающем в параллельном доступе к смежным блокам, где в строку кэша не загружаются ненужные данные.


0

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


0

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


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

0

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

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

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

Иногда в своей жизни я узнал, что приращение префикса происходит быстрее ...

for (int i = 0; i < MAX; ++i)

... чем приращение постфикса:

for (int i = 0; i < MAX; i++)

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

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


0

Мне просто повезло, что мне не пришлось об этом слишком беспокоиться, или я плохой программист?

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

В какой-то степени производительность всегда является требованием. Если вы можете ударить его, не думая об этом, вы вправе не думать об этом.

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

Мой вопрос: почему так много программистов так заботятся? Это действительно проблема для большинства разработчиков,

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

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

Кнут был прав: преждевременная оптимизация - корень всего зла. Но как только это сработает, каков следующий шаг? Быстро верно? НЕТ! Следующий шаг читабелен. Читаемый - это первый, следующий, средний и последний шаг. Многие из людей, которых я нахожу, делая ненужные оптимизации производительности, бросают читаемость под шину.

Некоторые даже получают извращенный трепет от того, как нечитаем их код. Им приходилось страдать, глядя на трудный для понимания код, созданный другими, так что теперь их очередь окупаться.

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

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.