В информатике , оптимизации программ , оптимизации кода, или оптимизации программного обеспечения является процесс модификации программной системы , чтобы сделать какой - то аспект его работу более эффективно и использовать меньше ресурсов. [1] В общем, компьютерная программа может быть оптимизирована так, чтобы она выполнялась быстрее, или чтобы она могла работать с меньшим объемом памяти или другими ресурсами, или потреблять меньше энергии.
Общий
Хотя акции слово «оптимизация» тот же корень , как «оптимальный», это редкий для процесса оптимизации для получения действительно оптимальную систему. Система в общем случае может быть оптимальным не в абсолютном выражении, но только в отношении данного качества метрики, который может быть в отличие от других возможных метрик. В результате, оптимизированная система обычно будет только оптимальным в одном приложении или для одной аудитории. Можно было бы уменьшить количество времени , которое программа берет , чтобы выполнить какую - то задачу по цене , что делает его потреблять больше памяти. В приложении , где объем памяти на награде, один может сознательно выбрать более медленный алгоритм для того , чтобы использовать меньше памяти. Часто нет «один размер подходит всем» дизайн , который хорошо работает во всех случаях, поэтому инженеры делают компромиссы , чтобы оптимизировать атрибуты , представляющие наибольший интерес. Кроме того, усилия, необходимые для того, чтобы сделать часть программного обеспечения полностью оптимальной - неспособной к дальнейшим улучшениям, - почти всегда превышают разумные пределы получаемых выгод; поэтому процесс оптимизации может быть остановлена до того, как полностью оптимальным решением было достигнуто. К счастью, это часто бывает , что наибольшие улучшения приходят в начале процесса.
Даже для данной метрики качества (таких как скорость выполнения), большинство методов оптимизации только улучшить результат; они не претендуют на получение оптимального результата. Superoptimization является процесс поиска действительно оптимальный выход.
Уровни оптимизации
Оптимизация может происходить на нескольких уровнях. Обычно более высокие уровни оказывают большее влияние, и их труднее изменить в дальнейшем в проекте, что требует значительных изменений или полной переписывания, если их нужно изменить. Таким образом, оптимизация, как правило, может продолжаться путем уточнения от большего к меньшему, при этом первоначальный выигрыш будет больше и достигается меньшими затратами, а последующий выигрыш будет меньше и требует большей работы. Однако, в некоторых случаях общая производительность зависит от производительности самих участков низкоуровневой программы, и небольшие изменения на поздней стадии или в начале рассмотрения низкоуровневых деталей может иметь негабарит воздействие. Как правило, некоторое внимание уделяется эффективности в рамках проекта - хотя это значительно варьируется - но основная оптимизация часто рассматривается уточнение должно быть сделано поздно, если когда-либо. На более длинных выполняющихся проектах там, как правило, циклы оптимизации, где улучшение в одной области выявляет ограничения в другом, и они, как правило, свернули, когда производительность является приемлемой или выгоды становятся слишком маленькими или дорогостоящими.
Поскольку производительность является частью спецификации программы - необычно медленная программа не подходит для этой цели: видеоигра с частотой 60 Гц (кадров в секунду) приемлема, но 6 кадров в секунду недопустимо нестабильна - производительность является рассмотрение с самого начала, чтобы убедиться , что система способна обеспечить достаточную производительность, и ранние прототипы должны иметь примерно приемлемую производительность там быть уверенность в том , что окончательная система (с оптимизацией) достижения приемлемой производительности. Это иногда опускается в убеждении , что оптимизация всегда может быть сделано позже, в результате чего в системах прототипа, которые слишком медленно - часто на порядок или более - и систем , которые в конечном счете являются отказы , потому что они архитектурно не могут достичь своих целей производительности, такие как Intel 432 (1981); или те , которые занимают годы работы для достижения приемлемой производительности, таких как Java (1995), которая достигается только приемлемую производительность с HotSpot (1999). Степень , в которой производительность изменяется между прототипом и производственной системой, и как поддающимся это для оптимизации, может быть существенным источником неопределенности и риски.
проектный уровень
На самом высоком уровне дизайн может быть оптимизирован для наилучшего использования доступных ресурсов с учетом целей, ограничений и ожидаемого использования / нагрузки. Архитектурный дизайн системы в подавляющем большинстве случаев влияет на его производительность. Например, система с привязкой к сетевой задержке (где сетевая задержка является основным ограничением для общей производительности) должна быть оптимизирована для минимизации сетевых отключений, в идеале выполняя один запрос (или без запросов, как в протоколе push ), а не несколько круглые поездки. Выбор дизайна зависит от целей: при разработке компилятора , если быстро компиляция является приоритетом ключа, один проход компилятор быстрее , чем многопроходной компилятор (предполагая такой же работу), но если скорость выходного кода является целью, медленнее многопроходной компилятор выполняет цель лучше, даже если это займет больше времени сам по себе. Выбор платформы и языка программирования происходит на этом уровне, и их изменение часто требует полной перезаписи, хотя модульная система может допускать перезапись только некоторых компонентов - например, программа Python может перезаписывать критические для производительности разделы на C. система, выбор архитектуры ( клиент-сервер , равноправных узлов ЛВС , и т.д.) происходит на уровне проектирования, и может быть трудно изменить, особенно если все компоненты не могут быть заменены в синхронизации (например, старые клиенты).
Алгоритмы и структуры данных
Учитывая общий дизайн, хороший выбор эффективных алгоритмов и структур данных , а также эффективной реализации этих алгоритмов и структур данных идет дальше. После разработки выбор алгоритмов и структур данных влияет на эффективность больше, чем любой другой аспект программы. Как правило, структуры данных сложнее изменить, чем алгоритмы, поскольку предположение о структуре данных и ее предположения о производительности используются во всей программе, хотя это можно минимизировать, используя абстрактные типы данных в определениях функций и ограничивая конкретные определения структур данных. в несколько мест.
Для алгоритмов это в первую очередь состоит в обеспечении того, чтобы алгоритмы были постоянными O (1), логарифмическими O (log n ), линейными O ( n ) или, в некоторых случаях, логарифмическими O ( n log n ) на входе (оба в пространстве и время). Алгоритмы с квадратичной сложностью O ( n 2 ) не масштабируются, и даже линейные алгоритмы вызывают проблемы при повторном вызове и обычно заменяются постоянными или логарифмическими, если это возможно.
Помимо асимптотического порядка роста, постоянные факторы вещества: асимптотический медленнее алгоритм может быть быстрее или меньше (потому что проще) , чем асимптотический быстрее алгоритм , когда они оба столкнулись с небольшим входом, который может быть так , что происходит в действительности. Часто гибридный алгоритм обеспечит лучшую производительность, благодаря этому компромиссу меняющегося с размером.
Общий метод повышения производительности - избегать работы. Хорошим примером является использование быстрого пути для общих случаев, повышающее производительность за счет исключения ненужной работы. Например, с использованием простого алгоритма компоновки текста для латинского текста, переключение на сложный алгоритм компоновки только для сложных скриптов, таких как Деванагари . Еще один важный метод кэширование, в частности , запоминания , что позволяет избежать избыточных вычислений. Из - за важности кэширования, часто много уровней кэширования в системе, что может вызвать проблемы с использованием памяти, и корректность вопросов из лежалых кэшей.
Уровень Исходный код
Помимо общих алгоритмов и их реализации на абстрактной машине, выбор уровня конкретного исходного кода может иметь большое значение. Например, на ранних компиляторов, while(1)
был медленнее , чем for(;;)
для безусловного цикла, потому что while(1)
оценивали 1 , а затем имел условный переход , который испытан , если это было верно, в то время for (;;)
имел безусловный переход. Некоторые оптимизации (например, этот) в настоящее время могут быть выполнены путем оптимизации компиляторов . Это зависит от исходного языка, целевого машинного языка и компилятора и может быть трудным для понимания или прогнозирования и может меняться с течением времени; это ключевое место, где понимание компиляторов и машинного кода может улучшить производительность. Loop-инвариантным движение кода и оптимизации возвращаемого значения являются примерами оптимизации , которые уменьшают потребность в дополнительном переменных и даже может привести к более высокой производительности, избегая окольные оптимизации.
уровень сборки
Между источником и уровнем компиляции, директивы и флаги сборки могут быть использованы для вариантов настройки производительности в исходном коде и компилятор , соответственно, например, с помощью препроцессора Определяет , чтобы отключить ненужные функции программного обеспечения, оптимизации для конкретных моделей процессоров или аппаратных возможностей, или предсказания ветвления , например. Источник система распространения программного обеспечения , такие как BSD «s Порты и Gentoo » s Portage может воспользоваться этой формой оптимизации.
Compile уровень
Использование оптимизирующего компилятора имеет тенденцию гарантировать, что исполняемая программа оптимизирована, по крайней мере, настолько, насколько компилятор может предсказать.
на уровне ассемблера
На самом низком уровне, написание кода с использованием языка ассемблера , предназначенным для конкретной аппаратной платформы может производить наиболее эффективный и компактный код , если программист пользуется полным репертуаром машинных инструкций . По этой причине многие операционные системы, используемые во встроенных системах , традиционно писались на ассемблере. Программы (кроме очень маленьких программ) редко написаны от начала до конца в сборе из - за затрат времени и средств , участвующих. Большинство из них скомпилировано с языка высокого уровня на ассемблер и оптимизировано вручную оттуда. Когда эффективность и размер менее важны большие части могут быть написаны на языке высокого уровня.
С более современных оптимизирующих компиляторов и большей сложностью последних процессоров , это труднее писать более эффективный код , чем то , что генерирует компилятор, и несколько проектов нужен этот «окончательный» шаг оптимизации.
Большая часть написанного сегодня кода предназначена для работы на максимально возможном количестве машин. Как следствие, программисты и составители не всегда используют в своих интересах более эффективных инструкций, предоставленных новыми процессорами или причуды старых моделей. Кроме того, код сборки настроен для конкретного процессора без использования таких инструкций могут все еще быть Субоптимальными на другой процессоре, ожидая другую настройку коды.
Как правило , сегодня вместо того , чтобы писать на языке ассемблера, программисты использовать дизассемблер для анализа вывод компилятора и изменять исходный код на высоком уровне , так что он может быть собран более эффективно, или понять , почему это неэффективно.
Время выполнения
Просто по времени компиляторы могут производить индивидуальные машинный код , основанный на данных во время выполнения, за счет компиляции накладных расходов. Эта техника датируется первыми регулярными выражения двигателей и получил широкое распространение с Java HotSpot и V8 для JavaScript. В некоторых случаях адаптивная оптимизация может выполнять оптимизацию времени выполнения, превышающую возможности статических компиляторов, путем динамической корректировки параметров в соответствии с фактическими входными данными или другими факторами.
Профиль наведением оптимизации является (AOT) компиляция оптимизация метод вперед-оф-времени на основе профилей времени выполнения, и похож на статический «средний случай» аналог динамической методики адаптивной оптимизации.
Самомодифицирующийся код может изменить себя в соответствии с условиями времени выполнения в целях оптимизации кода; это было более распространено в программах на ассемблере.
Некоторые конструкции ЦП могут выполнять некоторую оптимизацию во время выполнения. Некоторые примеры включают исполнение вне очереди , спекулятивное исполнение , конвейеры команд и предикторы ветвления . Составители могут помочь программе воспользоваться этими функциями процессора, например , путем планирования команд .
Платформы зависимые и независимые оптимизации
Оптимизация кода может быть также широко классифицированы как платформы -зависимые и независимых от платформы методов. В то время как последние будут эффективны на большинстве или во всех платформах, зависит от платформы методы используют специфические свойства одной платформы, либо полагаться на параметры в зависимости от одной платформы или даже на одном процессоре. Поэтому может потребоваться Дать или производить различные версии одного и того же кода для разных процессоров. Так , например, в случае оптимизации компиляции уровня, независимая от платформы методов являются универсальными методиками (таких как разворачивания петли , снижение вызовов функций, память эффективных процедуры, снижение условий и т.д.), что воздействие большинство архитектур процессоров в подобном способ. Отличный пример независимой от платформы оптимизации был показан с внутренним циклом for, где было замечено, что цикл с внутренним циклом for выполняет больше вычислений в единицу времени, чем цикл без него или цикл с внутренним циклом while. [2] Как правило, они служат для уменьшения общей длины пути команд , необходимой для завершения программы и / или уменьшить общее потребление памяти во время процесса. С другой стороны, зависит от платформы методы включают планирование команд, параллелизм на уровне команд , параллелизм на уровне данных, методы оптимизации кэша (т.е. параметры , которые различаются между различными платформами) и планирования инструкций оптимальным может отличаться даже на разных процессорах та же архитектура.
Снижение силы
Вычислительные задачи могут выполняться несколькими способами с разной эффективностью. Более эффективная версия с эквивалентной функциональностью известна как уменьшение прочности . Например, рассмотрим следующий C фрагмент кода , чье намерение состоит в том, чтобы получить сумму всех целых чисел от 1 до N :
int i , сумма = 0 ; для ( я = 1 ; я <= N ; ++ я ) { сумма + = я ; } Printf ( "сумма:% d \ п " , сумма );
Этот код может (не предполагая арифметическое переполнение ) можно переписать , используя математическую формулу , как:
INT сумма = Н * ( 1 + N ) / 2 ; printf ( "сумма:% d \ n " , сумма );
Оптимизация, иногда выполняется автоматически оптимизирующий компилятор, чтобы выбрать метод ( алгоритм ) , который является более вычислительно эффективными, при сохранении той же функциональности. См алгоритмической эффективности для обсуждения некоторых из этих методов. Тем не менее, значительное улучшение производительности часто может быть достигнуто путем удаления посторонние функциональности.
Оптимизация - не всегда очевидный или интуитивно понятный процесс. В приведенном выше примере, «оптимизированная» версия может быть медленнее , чем оригинальная версия , если N были достаточно малы и особенности аппаратных средств происходит гораздо быстрее при выполнении сложения и перекручивание операций , чем умножение и деление.
Компромиссы
В некоторых случаях, однако, оптимизация опирается на использование более сложных алгоритмов, что делает использование «особых случаев» и специальных «трюков» и выполняя сложные компромиссные. А «полностью оптимизированы» программа может быть более трудной для понимания и , следовательно , может содержать больше ошибок , чем неоптимизированные версии. Помимо устранения очевидных антипаттернов, некоторые оптимизации на уровне кода снижают ремонтопригодность.
Оптимизация, как правило , направлена на улучшение только один или два аспекта производительности: время выполнения, использование памяти, дисковое пространство, пропускную способность, потребляемую мощность или какой -либо другой ресурс. Это, как правило , требуется компромисс - где один фактор оптимизирован за счет других. Так , например, увеличение размера кэша улучшает производительность времени выполнения, но также увеличивает потребление памяти. Другие общие компромиссы включают код ясность и лаконичность.
Бывают случаи, когда программист, выполняющий оптимизацию, должен решить улучшить программное обеспечение для некоторых операций, но за счет снижения эффективности других операций. Эти компромиссы иногда могут быть не-технического характер - например, когда конкурент опубликовал сравнительный результат , который должен быть взбитым с целью улучшения коммерческого успеха , но приходит , возможно , с бременем сделать нормальное использование программного обеспечения менее эффективным. Такие изменения иногда в шутку называют пессимизациями .
Узкие места
Оптимизация может включать поиск узкого места в системе - компонента, ограничивающего производительность. С точки зрения кода, это часто будет горячая точка - критическая часть кода , который является основным потребителем необходимого ресурса - хотя это может быть еще одним фактором, например, О времени ожидания или пропускной способности ввода / сети.
В информатике потребление ресурсов часто следует форме распределения по степенному закону , и принцип Парето можно применить к оптимизации ресурсов, заметив, что 80% ресурсов обычно используются 20% операций. [3] Программное обеспечение в машиностроении, часто лучшее приближение , что 90% время выполнения компьютерной программы , затраченные на выполнение 10% кода (известную как 90/10 закона в данном контексте).
Более сложные алгоритмы и структуры данных хорошо работают со многими элементами, в то время как простые алгоритмы больше подходят для небольших объемов данных - настройка, время инициализации и постоянные коэффициенты более сложного алгоритма могут перевесить выгоду, и, следовательно, гибридный алгоритм или адаптивный алгоритм может быть быстрее , чем какой - либо одного алгоритма. Профилировщик производительности может использоваться, чтобы сузить круг решений о том, какая функциональность соответствует каким условиям. [4]
В некоторых случаях увеличение объема памяти может помочь ускорить выполнение программы. Например, программа фильтрации , обычно читать каждую строку и фильтр и вывод , что линии немедленно. Это использует достаточно памяти только для одной строки, но производительность обычно низкая из-за задержки каждого чтения с диска. Кэширование результата также эффективно, хотя также требует большего использования памяти.
При оптимизации
Оптимизация может уменьшить читаемость и добавить код , который используется только для улучшения производительности . Это может усложнить программы или системы, что делает их труднее поддерживать и отлаживать. В результате, оптимизация или настройка производительности часто выполняются в конце стадии разработки .
Дональд Кнут сделал следующие два заявления об оптимизации:
«Мы должны забыть о небольших эффективности, скажем , около 97% времени:. Преждевременная оптимизация есть корень всех зол Однако мы не должны упустить наши возможности в этой критической 3%» [5]
- (Он также приписывал цитату Тони Хоара несколько лет спустя, [6] , хотя это может быть допущена ошибка , как Хора отказывается от того , отчеканил фразу. [7] )
«В установленных инженерных дисциплин улучшение на 12%, легко получить, никогда не считается маргинальной , и я считаю , что та же точка зрения должна превалировать в программной инженерии» [5]
«Преждевременная оптимизация» - это фраза, используемая для описания ситуации, когда программист позволяет соображениям производительности влиять на дизайн фрагмента кода. Это может привести к тому, что дизайн будет не таким чистым, как мог бы, или код неправильный, потому что код усложняется оптимизацией, а программист отвлекается на оптимизацию.
При решении вопроса оптимизации определенной части программы, Закон Амдаля всегда следует учитывать: влияние на общей программе очень сильно зависит от того , сколько времени на самом деле провел в этой конкретной части, что не всегда ясно , глядя на коде без анализа производительности .
Поэтому лучший подход - сначала спроектировать код из проекта, а затем профилировать / тестировать полученный код, чтобы увидеть, какие части следует оптимизировать. Простой и элегантный дизайн часто легче оптимизируют на данном этапе, и профилирование может выявить неожиданные проблемы с производительностью , которые не были бы рассмотрены преждевременной оптимизации.
На практике часто бывает необходимо, чтобы цели производительности в виду, когда первое программное обеспечение проектирования, но программист уравновешивает цели проектирования и оптимизации.
Современные компиляторы и операционные системы настолько эффективны, что запланированное повышение производительности часто не может быть реализовано. Например, кэширование данных на уровне приложения, которые снова кэшируются на уровне операционной системы, не дает улучшений в исполнении. Тем не менее, это редкий случай, когда программист будет удалить прерванную оптимизацию от производства кода. Верно также и то, что достижения в области аппаратного обеспечения чаще всего устраняют любые потенциальные улучшения, но скрывающий код будет сохраняться в будущем еще долгое время после того, как его цель будет отвергнута.
Макросы
Оптимизация во время разработки кода с использованием макросов принимает разные формы на разных языках.
В некоторых процедурных языках, таких как C и C ++ , макросы реализуются с использованием подстановки токенов. В настоящее время встроенные функции во многих случаях могут использоваться в качестве альтернативы типобезопасности . В обеих случаях встраиваемого тело функции может затем подвергается дальнейшей оптимизации во время компиляции компилятора, в том числе постоянного складывания , которые могут двигаться некоторыми вычисления времени компиляции.
Во многих языках функционального программирования макросы реализуются с использованием замены синтаксических деревьев / абстрактных синтаксических деревьев во время синтаксического анализа, что, как утверждается, делает их более безопасными в использовании. Поскольку во многих случаях используется интерпретация, это один из способов гарантировать, что такие вычисления выполняются только во время синтаксического анализа, а иногда и единственный способ.
Лисп возник этот стиль макро, [ править ] и такие макросы часто называют «Lisp-подобных макросов.» Аналогичный эффект может быть достигнут при использовании шаблона метапрограммирования в C ++ .
В обоих случаях работа перемещается во время компиляции. Разница между макросами C, с одной стороны, и макросами, подобными Lisp, и метапрограммированием шаблонов C ++, с другой стороны, заключается в том, что последние инструменты позволяют выполнять произвольные вычисления во время компиляции / синтаксического анализа, в то время как раскрытие макросов C не выполняет никаких действий. вычисление и зависит от способности оптимизатора выполнять его. Кроме того, макросы C не поддерживают напрямую рекурсию или итерацию , поэтому не являются полными по Тьюрингу .
Как и при любой оптимизации, однако, часто бывает трудно предсказать, где такие инструменты будут иметь наибольшее влияние, прежде чем проект будет завершен.
Автоматизированная и ручная оптимизация
Смотрите также Категория: Оптимизация компилятора
Оптимизация может быть автоматизирована компиляторами или выполнена программистами. Доходы, как правило , ограничены для локальной оптимизации, и больше для глобальных оптимизаций. Как правило, самые мощные оптимизации, чтобы найти превосходный алгоритм .
Оптимизацией всей системы обычно занимаются программисты, потому что это слишком сложно для автоматических оптимизаторов. В этой ситуации программисты или системные администраторы явно изменяют код, чтобы система в целом работала лучше. Хотя это может привести к более высокой эффективности, это гораздо дороже , чем автоматизированные оптимизации. Поскольку многие параметры влияют на производительность программы, оптимизация программного пространство велико. Метаэвристика и машинное обучение используются для решения сложных задач оптимизации программ. [8]
Используйте профилировщик (или анализатор производительности ), чтобы найти разделы программы, которые используют больше всего ресурсов - узкое место . Программисты иногда считают , что они имеют четкое представление о том, где узком месте , но интуиция часто неправильно. [ Править ] Оптимизация незначительную часть кода, как правило , мало , чтобы помочь общей производительности.
Когда узкое место локализовано, оптимизация обычно начинается с переосмысления алгоритма, используемого в программе. Чаще всего конкретный алгоритм может быть специально адаптирован к конкретной проблеме, обеспечивая лучшую производительность, чем общий алгоритм. Например, задача сортировки огромного списка элементов обычно выполняется с помощью процедуры быстрой сортировки , которая является одним из наиболее эффективных общих алгоритмов. Но если какая - то характеристика элементов является годной для использования (например, они уже расположены в каком - то определенном порядке), другой метод может быть использован, или даже на заказ рода рутину.
После того , как программист с достаточной степенью уверенности , что выбран лучший алгоритм оптимизации кода может начаться. Петли может быть раскатали (для нижней петли над головой, хотя это может часто приводить к снижению скорости , если он перегружает кэш процессора ), тип данных как можно меньше может быть использованы, целочисленная арифметика может быть использована вместо чисел с плавающей точкой, и так далее . (См алгоритмической эффективности статьи для этих и других методов.)
Узкие места производительности могут быть из - за языковые ограничения , а не алгоритмы или структуры данных , используемые в программе. Иногда критическая часть программы может быть переписана в другом языке программирования , который дает более прямой доступ к основной машине. Например, он является общим для очень высокого уровня языков , таких как Python , чтобы иметь модули , написанные на C для большей скорости. Программы, уже написанные на C, могут иметь модули, написанные на ассемблере . Программы, написанные на D, могут использовать встроенный ассемблер .
Переписывание разделов «окупается» в этих обстоятельствах благодаря общему «практическому правилу », известному как закон 90/10 , который гласит, что 90% времени тратится на 10% кода и только 10% времени. в остальных 90% кода. Таким образом, интеллектуальные усилия по оптимизации лишь небольшой части программы могут иметь огромное влияние на общую скорость - если удастся найти правильную часть (части).
Руководство по оптимизации иногда имеет побочный эффект подрыва читаемости. Таким образом, оптимизации кода должны быть тщательно задокументированы (желательно с использованием встроенных комментариев), а их влияние на будущее развитие должно быть оценено.
Программа, выполняющая автоматическую оптимизацию, называется оптимизатором . Большинство оптимизаторов встроены в компиляторы и работать во время компиляции. Оптимизаторы часто могут адаптировать сгенерированный код к конкретным процессорам.
Сегодня автоматизированная оптимизация почти полностью ограничивается оптимизацией компилятора . Однако, поскольку оптимизации компилятора, как правило , ограничены фиксированный набор достаточно общих оптимизации, существует значительный спрос на оптимизаторы , которые могут принимать описания проблемы и язык конкретных оптимизаций, позволяя инженер задать пользовательские оптимизации. Инструменты, которые принимают описания оптимизаций, называются системами преобразования программ и начинают применяться к реальным программным системам, таким как C ++.
Некоторые языки высокого уровня ( Eiffel , Esterel ) оптимизируют свои программы, используя промежуточный язык .
Грид-вычисления или распределенные вычисления направлены на оптимизацию всей системы путем переноса задач с компьютеров с интенсивным использованием на компьютеры с простоями.
Время, затраченное на оптимизацию
Иногда, время, необходимое для проведения оптимизации в них само по себе может быть проблемой.
Оптимизация существующего кода , как правило , не добавляет новые функции, и что еще хуже, это может добавить новые ошибки в ранее работающий код (как любое изменение может). Поскольку код, оптимизированный вручную, иногда может иметь меньшую «читаемость», чем неоптимизированный код, оптимизация также может повлиять на его ремонтопригодность. Оптимизация имеет свою цену, и важно быть уверенным, что вложения окупаются.
Автоматический оптимизатор (или оптимизирующий компилятор , программа, оптимизация выполняет код) может сам по себе должна быть оптимизирована, либо в целях дальнейшего повышения эффективности целевых программ или еще ускорить его собственную работу. Компиляция выполняется с оптимизацией «включен» , как правило , занимает больше времени, хотя это, как правило , только проблема , когда программы довольно велики.
В частности, для точно в сроке компиляторов производительность время выполнения компонента компиляции, выполнения вместе с его целевым кодом, является ключом к повышению общей скорости выполнения.
Рекомендации
- Джон Бентли : Написание эффективных программ , ISBN 0-13-970251-2 .
- Дональд Кнут : искусство программирования
- ^ Роберт Седжвик , Алгоритмы , 1984, стр. 84.
- ^ Adewumi, Tosin П. (2018-08-01). «Конструкция программы внутреннего цикла: более быстрый способ выполнения программы» . Open Computer Science . 8 (1): 115-122. DOI : 10,1515 / сост-2018-0004 .
- ^ Уэскотт, Боб (2013). Каждый производительности компьютера Книга, Глава 3: Полезные законы . CreateSpace . ISBN 978-1482657753.
- ^ «Профилирование производительности с фокусом» . Проверено 15 августа 2017 года .
- ^ а б Кнут, Дональд (декабрь 1974 г.). «Структурное программирование с ходом к отчетности». ACM Computing Surveys . 6 (4): 268. CiteSeerX 10.1.1.103.6084 . DOI : 10.1145 / 356635.356640 .
- ↑ Ошибки TeX , в программном обеспечении - Практика и опыт , том 19, выпуск 7 (июль 1989 г.), стр. 607–685, перепечатанный в его книге «Грамотное программирование» (стр. 276).
- ^ «Преждевременная оптимизация - корень всех зол» . hans.gerwitz.com . Проверено 18 декабря 2020 .
Однако Хоар не утверждал этого, когда я спросил его в январе 2004 года.
- ^ Мемети, Суэйб; Пллана, Сабри; Binotto, Alécio; Колодзей, Иоанна; Брандич, Ивона (26 апреля 2018 г.). «Использование метаэвристики и машинного обучения для оптимизации программного обеспечения параллельных вычислительных систем: систематический обзор литературы». Вычислительная техника . Springer Вена. 101 (8): 893–936. arXiv : 1801.09444 . Bibcode : 2018arXiv180109444M . DOI : 10.1007 / s00607-018-0614-9 .
Внешние ссылки
- Как написать Fast Числовой код: небольшое введение
- «Что каждый программист должен знать о памяти» Ульриха Дреппера - объясняет структуру современных подсистем памяти и предлагает способы их эффективного использования.
- «Linux многожильного Анализ производительности и оптимизация в миниатюре» , слайды презентации Филиппа Mucci
- Программирование Оптимизация Пол Hsieh
- Написание эффективных программ («Правила Бентли») . Джон Бентли.
- "Performance Anti-Patterns" Барт Smaalders