
- •Содержание курса “Теория алгоритмов и вычислительных процессов”
- •I. Теория алгоритмов
- •Основные понятия теории алгоритмов
- •1.1. Предварительные сведения
- •1.2. Основные требования к алгоритмам
- •1.3. Необходимость математического понятия алгоритма
- •2. Типы алгоритмов
- •3. Способы представления (описания) алгоритмов
- •3.1. Исполнитель алгоритма
- •3.2. Строчная словесная запись алгоритма
- •3.3. Графическая форма записи
- •3.4. Управляющие структуры
- •4. Описание задачи и выбор алгоритма
- •5. Универсальные алгоритмические модели
- •Понятие конструктивного объекта
- •Понятие об алфавитных алгоритмах
- •5.3. Формализация понятия “алгоритм”
- •5.4. Схема построения алгоритмической системы
- •6. Рекурсивные функции
- •6.1. Примитивно-рекурсивные функции
- •6.1.1. Оператор суперпозиции (подстановки)
- •6.1.2. Оператор примитивной рекурсии
- •6.2. Частично-рекурсивные функции
- •Пример 6.2.2. Рассмотрим функцию
- •6.3. Тезис Черча
- •7. Машины Тьюринга (Поста)
- •7.1. Основные понятия машин Тьюринга
- •7.2. Способы представления машины Тьюринга
- •7.2.1. Представление машины Тьюринга совокупностью команд
- •7.2.2. Представление машины Тьюринга графом
- •7.2.3. Представление машины Тьюринга таблицей соответствия
- •7.3. Примеры построения машин Тьюринга
- •Вычислимость по Тьюрингу
- •7.5. Некоторые операции над машиной Тьюринга
- •7.5.1. Композиция машин Тьюринга
- •7.5.2. Итерация машины Тьюринга
- •7.5.3. Разветвление машин Тьюринга
- •7.4. Универсальная машина Тьюринга
- •7.5. Тезис Тьюринга
- •7.6. Машина Поста
- •9. Алгоритмическая разрешимость. Алгоритмические проблемы
- •10. Сложность алгоритмов и вычислений
- •Анализ скорости выполнения алгоритмов
- •Память или время
- •Временнáя сложность алгоритма
- •Оценка с точностью до порядка
- •Определение сложности
- •Сложность рекурсивных алгоритмов
- •Средний и наихудший случай
- •Общие функции оценки сложности
- •Скорость работы алгоритма в реальных условиях
- •19.5. Труднорешаемые задачи
Скорость работы алгоритма в реальных условиях
Несмотря на то, что малые члены и постоянные множители отбрасываются при изучении сложности алгоритмов, часто их необходимо учитывать для фактического написания программ. Эти числа становятся особенно важными, когда размер задачи мал, а константы большие.
Предположим, нужно рассмотреть два алгоритма, которые выполняют одну и ту же задачу. Первый выполняет ее за время O(N), а второй - за время O(N2). Для больших N первый алгоритм, вероятно, будет работать быстрее.
При более близком рассмотрении обнаруживается, что первый описывается функцией f(N) = 30*N + 7000, а второй - f(N) = N2. В этом случае второй алгоритм при N меньше 100 существенно быстрее. Если вы знаете, что размер данных задачи не превышает 100, то целесообразнее использовать второй алгоритм.
С другой стороны, время выполнения разных инструкций может сильно отличаться. Если первый алгоритм использует быстрые операции с памятью, а второй - медленное обращение к диску, то первый алгоритм будет эффективнее в любом случае.
Проблему выбора оптимального алгоритма осложняют и другие факторы. Например, первый алгоритм может требовать больше памяти, чем установлено на компьютере. Но на реализацию второго алгоритма, если он гораздо сложнее, может уйти больше времени, а его отладка превратится в настоящий кошмар. Иногда подобные практические соображения могут сделать теоретический анализ сложности алгоритма почти бессмысленным.
Тем не менее анализ сложности помогает понять особенности алгоритмов и определить, в каком месте программы производится большая часть вычислений. Усовершенствовав код в этих частях, можно существенно увеличить производительность программы в целом.
Иногда лучшим способом для определения наиболее эффективного алгоритма является тестирование. При этом важно, чтобы использовались данные, максимально приближенные к реальным условиям. В обратном случае результаты тестирования могут сильно отличаться от действительных.
При работе в реальных условиях очень важным фактором является частота обращения к файлу подкачки (page file). Операционная система Windows резервирует определенный объем дискового пространства под виртуальную память. Когда реальная память заполнена, Windows записывает часть ее содержимого на диск. Этот процесс называется страничной подкачкой, потому что Windows сбрасывает информацию в участки памяти, называемые страницами. Освободившуюся реальную память операционная система использует для других целей. Страницы, записанные на диск, могут быть подгружены системой при обращении к ним обратно в память.
Поскольку доступ к диску намного медленнее, чем доступ к реальной памяти, слишком частое обращение к файлу подкачки может очень сильно замедлять производительность приложения. Если программа работает с огромными объемами памяти, система будет часто обращаться к диску, что существенно замедляет работу.
Когда начинается процесс создания файлов подкачки, скорость работы программы сильно падает. Когда весь массив данных располагается в оперативной памяти, требуется одинаковое время для обращения к его элементам по порядку или случайным образом. Как только начинается подкачка, случайный доступ к памяти гораздо менее эффективен.
Существует несколько способов минимизации эффектов подкачки. Основной прием – экономное расходование памяти. Помните, что программа не может занять всю физическую память, так как часть ее используется под систему и другие программы. Второй способ – написать код так, чтобы программа обращалась к ячейкам физической памяти перед тем, как перейти к другим частям массива.