Здравствуйте прошла курсы на тему Алгоритмы С++. Но не пришел сертификат и не доступен.Где и как можно его скаачат? |
Специальные методы сортировки
Внешняя сортировка
Теперь мы переходим к рассмотрению другой абстрактной задачи сортировки. Она возникает, когда сортируемый файл настолько велик, что не помещается целиком в оперативной памяти компьютера. Для описания таких ситуаций используется термин внешняя сортировка (external sorting). Существует множество различных видов устройств внешней сортировки, которые накладывают различные ограничения на элементарные операции, применяемые при их реализации. Все же будет полезно изучить методы сортировки, использующие две примитивные базовые операции: операцию считать данные из внешнего запоминающего устройства в оперативную память и операцию записать данные из оперативной памяти на внешнее запоминающее устройство. Предполагается, что стоимость этих двух операций настолько выше стоимости примитивных вычислительных операций, что последние можно полностью игнорировать. Например, в этой абстрактной модели полностью игнорируются затраты на сортировку в оперативной памяти! При очень большой оперативной памяти и неэффективных методах сортировки это предположение может оказаться неверным, но при расчете общей стоимости внешней сортировки в практических ситуациях эти затраты обычно можно учесть дополнительными коэффициентами.
В силу многообразия характеристик и стоимости внешних запоминающих устройств разработка методов внешней сортировки сильно зависит от состояния технологии на текущий момент. Эти методы могут оказаться очень сложными, а их производительность зависит от многих параметров; и в исследовании методов внешней сортировки могут оказаться недооцененными и невостребованными искусные методы - только в силу тех или иных изменений в технологии. По этой причине в данном разделе мы не будем заниматься вопросами разработки конкретных реализаций, а рассмотрим общие принципы внешней сортировки.
Кроме высокой стоимости операций чтения-записи, часто возникают и другие жесткие требования, предъявляемые к доступу к данным конкретными внешними устройствами. Например, для большинства типов устройств операции чтения и записи между внешним запоминающим устройством и оперативной памятью обычно наиболее эффективно выполняются при передаче крупных блоков данных. Кроме этого, внешние устройства очень большой емкости часто создаются так, что максимальной производительности они достигают при последовательном доступе к блокам данных. Например, невозможно прочитать элементы данных, находящиеся в конце магнитной ленты, не просмотрев элементы, хранящиеся в начале ленты - на практике доступ к элементам, записанным на магнитной ленте, ограничен теми элементами, которые расположены рядом с последними прочитанными элементами. Тем же свойством обладают и некоторые современные технологии. Поэтому в данном разделе мы сосредоточимся на изучении методов, которые последовательно считывают и записывают крупные блоки данных, неявно предполагая, что для машин и устройств интересующих нас типов доступны быстродействующие реализации этого вида доступа к данным.
При выполнении считывания или записи нескольких различных файлов мы будем полагать, что все эти файлы находятся на различных внешних запоминающих устройствах. На старых вычислительных машинах, в которых файлы хранились на сменных магнитных лентах, это предположение было обязательным требованием. При работе с магнитными дисками становятся возможными реализации алгоритмов, использующих единственное внешнее устройство, но все же обычно работа с несколькими устройствами более эффективна.
Первым шагом при создании высокоэффективной программы сортировки очень больших файлов является реализация эффективной программы копирования файла. Вторым шагом может быть реализация программы инвертирования порядка записей в файле. Все трудности, с которыми приходится сталкиваться при решении этих задач, возникают и при реализации внешней сортировки. (В процессе сортировки иногда приходится выполнять одну из этих операций.) Цель использования абстрактной модели состоит в том, чтобы отделить вопросы построения таких реализаций от вопросов разработки алгоритма.
Рассматриваемые нами алгоритмы сортировки организованы в виде последовательности проходов по всем данным, и стоимость того или иного метода внешней сортировки обычно определяется просто подсчетом количества таких проходов. Чаще всего требуется сравнительно небольшое число проходов - может быть, десять или меньше. Из этого следует, что уменьшение этого числа проходов хотя бы на один существенно повышает производительность алгоритма. Наше основное предположение заключается в том, что основную долю времени выполнения конкретного метода внешней сортировки составляют операции ввода и вывода данных. Следовательно, время выполнения внешней сортировки можно вычислить, умножив число выполняемых ею проходов на время, необходимое для считывания и записи всего файла.
Короче говоря, абстрактная модель внешней сортировки, которой мы в дальнейшем будем пользоваться, построена на предположении, что сортируемый файл слишком велик, чтобы полностью разместить его в оперативной памяти, и зависит от двух других параметров: времени выполнения сортировки (число проходов по данным) и количества доступных внешних устройств. Мы полагаем, что в нашем распоряжении имеются
- N сортируемых записей, расположенных на внешнем устройстве,
- объем оперативной памяти, достаточный для размещения M записей, и
- 2Р внешних устройств, которыми можно пользоваться во время сортировки.
Пометим внешнее устройство, на котором находится файл входных данных, меткой 0, а остальные внешние устройства - метками 1, 2, ..., 2P - 1. Цель сортировки заключается в том, чтобы поместить записи на устройство 0 в отсортированном виде. Как мы вскоре увидим, существует зависимость между P и общим временем выполнения сортировки, и было бы хорошо получить явное выражение этой зависимости, чтобы иметь возможность сравнивать различные стратегии.
Существует много причин, в силу которых эта идеализированная модель может не соответствовать действительности. Тем не менее, как и всякая хорошая абстрактная модель, она отображает наиболее важные аспекты реальной ситуации и очерчивает точные рамки, внутри которых можно проводить исследования алгоритмических идей, многие из которых непосредственно применяются в практических ситуациях.
Большая часть методов внешней сортировки основана на следующем общем принципе: выполняется первый проход по сортируемому файлу, в процессе которого производится его разбиение на блоки с размером, примерно равным объему доступной оперативной памяти, и эти блоки сортируются. Затем отсортированные блоки сливаются - если необходимо, за несколько проходов по файлу, при этом с каждым проходом размер отсортированных блоков возрастает, пока весь файл не станет упорядоченным. Такой подход называется сортировкой-слиянием (sort-merge), он с успехом используется на практике с пятидесятых годов прошлого столетия, когда компьютеры впервые стали широко применяться в коммерческих приложениях.
Простейшая стратегия сортировки-слияния, называемая сбалансированное многопутевое слияние (balanced multiway merging), показана на рис. 11.12. Этот метод состоит из прохода, выполняющего начальное распределение (initial distribution), за которым следуют несколько проходов многопутевого слияния (multiway merging pass).
Во время начального прохода входные данные распределяются по внешним устройствам P, P + 1, ..., 2P - 1 в виде отсортированных блоков данных по M записей (за исключением, возможно, последнего блока, который меньше остальных, если N не кратно M). Такое распределение нетрудно выполнить: мы считываем первые M записей с входного устройства, сортируем их и записываем упорядоченный блок на устройство P ; затем считываем с входного устройства следующие M записей, сортируем их и записываем упорядоченный блок на устройство P + 1 и т.д. Если мы достигли устройства 2P - 1, и еще есть необработанные данные (т.е. если N > PM), мы записываем на устройство P второй отсортированный блок, затем второй блок на устройство P + 1 и т.д., до исчерпания всех входных данных. По завершении распределения количество отсортированных блоков, размещенных на каждом устройстве, равно N/PM, округленному до ближайшего целого числа в ту или другую сторону. Если N кратно M, то размеры всех блоков равны M (если это не так, то размер M имеют все блоки, за исключением последнего). Для небольших N количество блоков может оказаться меньше P, тогда одно или несколько устройств будут пустыми.
На первом проходе многопутевого слияния устройства в интервале от P до 2P - 1 рассматриваются как входные, а устройства в интервале от 0 до P - 1 как выходные.
На проходе начального распределения мы выбираем из входных данных элементы A S O, сортируем их и записываем упорядоченную последовательность A O S на первое выходное устройство. Далее мы выбираем из входных данных элементы R T I, сортируем их и записываем упорядоченную последовательность I R T на второе выходное устройство. Продолжая таким образом и циклически переключаясь между выходными устройствами, мы окончательно получаем 15 отрезков: по пять на каждом выходном устройстве. На первом этапе слияния сливаются отрезки A O S, I R T и A G N, и получается последовательность A A G I N O R S T, которую мы записываем на первое выходное устройство, затем выполняется слияние вторых отрезков на входных устройствах, и получается последовательность D E G G I M N N R, которую мы записываем на второе выходное устройство и т.д.; теперь получилось сбалансированное распределение данных на трех устройствах. После еще двух проходов слияния сортировка завершается.
Мы выполняем P-путевое слияние блоков данных размером M, помещенных на входные устройства, и получаем отсортированные блоки данных размером PM, которые максимально сбалансированно размещаем на выходных устройствах. Сначала сливаются первые блоки с каждого входного устройства, а результат этого слияния записывается на устройство 0, затем сливаются вторые блоки с каждого входного устройства и записываются на устройство 1 и т.д. После использования устройства P - 1 вторые блоки данных записываются на устройство 0, затем на устройство 1 и т.д. Этот процесс продолжается до тех пор, пока все входные данные не будут исчерпаны. После распределения количество отсортированных блоков на каждом устройстве равно N/PM, округленному до ближайшего целого числа в ту или другую сторону. Если N кратно PM, то все блоки имеют размер PM, иначе последний блок меньше остальных. Если N не больше PM, то остается один отсортированный блок (на устройстве 0), и на этом сортировка заканчивается.
В противном случае мы повторяем этот процесс и выполняем второй проход многопутевого слияния, рассматривая устройства 0, 1, ..., P - 1 в качестве входных, а устройства P, P + 1, ..., 2P - 1 в качестве выходных. В результате P-путевого слияния отсортированных блоков размером PM, размещенных на входных устройствах, получаются блоки размером P2M, которые размещаются на выходных устройствах. Сортировка заканчивается по завершении второго прохода (результат на устройстве P), если N не больше P2M.
Продолжая таким образом и переключаясь между устройствами от 0 до P - 1 и устройствами от P до 2P - 1, каждое P-путевое слияние увеличивает размер блоков в P раз, пока в конечном итоге не получится один блок, на устройстве 0 или на устройстве P. Последнее слияние на каждом проходе может не быть полным P-путевым слиянием, если это не так, то процесс хорошо сбалансирован. Этот процесс проиллюстрирован на рис. 11.13, где указаны только количество и относительные размеры отрезков. Оценку стоимости слияния можно получить, выполнив умножения, указанные в представленной на рисунке таблице, просуммировав результаты (без нижней строки) и поделив сумму на число первоначальных отрезков. Эти вычисления выражают затраты через количество проходов по данным.
Чтобы выполнить P-путевое слияние, можно воспользоваться очередью с приоритетами размером P. Нужно постоянно выбирать из каждого из P сливаемых упорядоченных блоков наименьший элемент из числа еще не выведенных, и затем заменять выведенный элемент следующим из того же блока. Для выполнения этой процедуры в очереди с приоритетами хранятся индексы устройств, значение ключа следующей записи считывается с указанного устройства (а по достижении конца блока выдается сигнальное значение, большее всех ключей в записях) и определяется функция <. Тогда само слияние сводится к простому циклу, который считывает очередную запись с устройства с минимальным ключом и выдает ее в выходной файл, после чего заменяет эту запись в очереди с приоритетами следующей записью с того же устройства, и так до тех пор, пока наименьший ключ в очереди с приоритетами не станет равным сигнальному значению. Можно воспользоваться реализацией пирамидального дерева и сделать время обслуживания очереди с приоритетами пропорциональным log P, но обычно P так мало, что эти затраты незаметны по сравнению с операциями записи на внешнее устройство. В нашей абстрактной модели мы игнорируем затраты на содержание очереди с приоритетами и предполагаем, что имеется эффективный метод последовательного доступа к данным на внешних устройствах, поэтому время выполнения можно измерять подсчетом количества проходов по данным. Для практических целей можно воспользоваться элементарной реализацией очереди с приоритетами и сосредоточить усилия на создании программ, обеспечивающих максимально производительное использование внешних устройств.
Распределение отрезков в сбалансированном 3-путевом слиянии
В процессе начального распределения сбалансированной трехпутевой сортировки-слияния файла, размер которого в 15раз больше размера оперативной памяти, на устройства 3, 4 и 5 записываются по 5 отрезков, размер которых в относительных единицах равен 1, а устройства 0, 1 и 2 остаются пустыми. На первом этапе слияния два отрезка размером 3 записываются на устройства 0 и 1, и один отрезок размером 3 на устройство 2, после чего устройства 3, 4 и 5 остаются пустыми. Далее выполняется слияние отрезков, находящихся на устройствах 0, 1 и 2, а результаты записываются снова на устройства 3, 4 и 5 и т.д., пока не останется только один отрезок на устройстве 0. Общее количество обработанных записей равно 60: четыре прохода по 15 записям.
Лемма 11.4. При наличии 2P внешних устройств и оперативной памяти, достаточной для размещения Mзаписей, сортировка-слияние на основе P-путевого сбалансированного слияния выполняет порядка проходов.
Один проход нужен для распределения. Если
N = MPk
, то блоки имеют размер MP после первого слияния,
MP2
после второго,
MP3
после третьего и т.д. Сортировка заканчивается после проходов. В противном случае, если
MPk-1k < N < MPk
, наличие неполных и пустых блоков приводит ближе к концу процесса к появлению различий в размерах блоков, но он все равно завершается после выполнения
проходов.
Например, если нужно отсортировать 1 миллиард записей, используя шесть внешних устройств и оперативную память, позволяющую разместить 1 миллион записей, это можно сделать с помощью трехпутевой сортировки-слияния, выполнив всего восемь проходов по данным: один проход начального распределения и проходов слияния. После начального распределения получаются отсортированные отрезки данных, содержащие по 1 миллиону записей, после первого слияния - по 3 миллиона записей, после второго слияния - по 9 миллионов записей, после третьего слияния - по 27 миллионов записей в каждом блоке и т.д. Можно подсчитать, что на сортировку файла уйдет в 9 раз больше времени, чем на его копирование.
Наиболее важное решение, которое приходится принимать на практике при подготовке сортировки-слияния - это выбор значения P, т.е. порядка слияния. В используемой нами абстрактной модели последовательный метод доступа накладывает ограничение, что P должно быть равно половине числа доступных внешних устройств. Такая модель реалистична для многих внешних запоминающих устройств. Однако существует множество других внешних запоминающих устройств, для которых возможен и не последовательный доступ, хотя его стоимость и больше. Если для сортировки доступно всего лишь небольшое количество внешних устройств, использование методов доступа, отличных от последовательного, становится неизбежным. В таких случаях все еще можно использовать многопутевое слияние, но при этом нужно учитывать, что увеличение значения P приводит к уменьшению числа проходов, но увеличивает количество (медленных) операций непоследовательного доступа.
Упражнения
11.35. В стиле примера, представленного на рис. 11.12, покажите, как ключи E A S Y Q U E S T I O N W I T H P L E N T Y O F K E Y S сортируются с помощью 3-путе-вого сбалансированного слияния.
11.36. Как отразится на количестве проходов многопутевого слияния удвоение количества внешних устройств?
11.37. Как отразится на количестве проходов многопутевого слияния увеличение объема доступной оперативной памяти в 10 раз?
11.38. Разработайте интерфейс для внешних входных и выходных устройств, который использует последовательную передачу блоков данных с асинхронно работающих внешних устройств (или подробно ознакомьтесь с существующим в вашей системе). Реализуйте с помощью этого интерфейса P-путевое слияние, чтобы P было максимально возможным при условии, что P входных файлов и выходной файл должны размещаться на различных выходных устройствах. Сравните время выполнения полученной программы с временем, необходимым для последовательного копирования файлов на выходные устройства.
11.39. Пользуясь интерфейсом из упражнения 11.38, напишите программу обращения порядка записей в файле максимально допустимого в вашей системе размера.
11.40. Как выполнить идеальное тасование всех записей на внешнем устройстве?
11.41. Разработайте модель стоимости многопутевого слияния, которое охватывает алгоритмы, способные переключаться с одного файла на другой на том же самом устройстве с фиксированной стоимостью переключения, которая намного превышает стоимость последовательного чтения.
11.42. Разработайте способ внешней сортировки, основанный на разбиении, подобном используемому в быстрой сортировке или MSD-сортировке, проанализируйте его и сравните с многопутевой сортировкой. Можно использовать высокий уровень абстракции, как при описании сортировки-слияния в этом разделе, однако нужно стремиться к тому, чтобы можно было спрогнозировать время выполнения для заданного числа устройств и заданного объема оперативной памяти.
11.43. Как отсортировать содержимое внешнего устройства, если недоступны любые другие внешние устройства (кроме оперативной памяти)?
11.44. Как отсортировать содержимое внешнего устройства, если доступно лишь еще одно устройство (а также оперативная память)?