Опубликован: 05.01.2015 | Доступ: свободный | Студентов: 2013 / 0 | Длительность: 63:16:00
Лекция 2:

Принципы анализа алгоритмов

Анализ алгоритмов

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

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

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

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

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

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

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

Первый шаг при анализе алгоритма состоит в определении абстрактных операций, на которых основан алгоритм, чтобы отделить анализ от реализации. Например, мы отделяем подсчет, сколько раз одна из реализаций алгоритма объединение-поиск запускает фрагмент кода i = a[i], от выяснения, сколько наносекунд требуется для выполнения этого фрагмента кода на данном компьютере. Для определения реального времени выполнения программы на конкретном компьютере требуются оба этих элемента. Первый из них определяется свойствами алгоритма, а второй - свойствами компьютера. Такое разделение зачастую позволяет сравнивать алгоритмы таким способом, который не зависит от определенной реализации или от определенного типа компьютера.

Количество используемых абстрактных операций может оказаться очень большим, однако производительность алгоритма, как правило, зависит от нескольких величин, причем наиболее важные для анализа величины обычно определить несложно. Один из способов их определения заключается в использовании механизма профилирования (подсчитывает количество выполнений каждой инструкции, доступен во многих реализациях С++) для нахождения наиболее часто исполняемых частей программы по результатам нескольких пробных запусков. Или же, как алгоритмы объединение-поиск из раздела 1.3 "Введение" , наша реализация может быть построена лишь на нескольких абстрактных операциях. В любом случае, анализ сводится к определению частоты исполнения нескольких фундаментальных операций. Принцип нашей работы заключается в том, чтобы отыскать приблизительные оценки этих величин, зная, что для важных программ при необходимости можно будет произвести полный анализ. Более того, как будет показано далее, часто можно достаточно точно предсказать результаты на основе приближенных аналитических результатов в сочетании с эмпирическим изучением.

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

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

Вначале, в разделе 2.3, рассматриваются математические функции, которые обычно нужны для описания характеристик производительности алгоритмов. Далее, в разделе 2.4, будет рассмотрена О-нотация (О-notation) и понятие пропорционально (is proportional to), которые позволяют опустить детали при математическом анализе. Затем, в разделе 2.5, изучаются рекуррентные соотношения (recurrence relations) - основной аналитический инструмент, используемый для выражения характеристик алгоритма в виде математических равенствах. И в завершение, в разделе 2.6, приводятся примеры, в которых все эти инструменты применяются для анализа конкретных алгоритмов.

Упражнения

  • 2.3. Напишите выражение вида с0 + c1N + c2N^2 + c3N3, которое точно описывает время выполнения программы из упражнения 2.2. Сравнить время, получаемое из этого выражения, с реальным при N = 10, 100, 1000.
  • 2.4. Напишите выражение, которое точно описывает время выполнения программы 1.1 в зависимости от M и N.
Никита Андриянов
Никита Андриянов
Дмитрий Уколов
Дмитрий Уколов
Юлия Романова
Юлия Романова
Россия, Республика Татарстан