avva: (Default)
[personal profile] avva
(эта запись будет интересна программистам и сочувствующим)

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

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

Автор алгоритма доказывает, путем довольно сложных и скучных выкладок, которые я не проверял, что его Dual-Pivot Quicksort теоретически должен быть быстрее обычного Quicksort в следующем смысле: он делает - на типичных входных данных - примерно столько же сравнений (comparisons), но на 20% меньше обменов элементами (swaps). Его практические измерения подверждают теорию. Интересно, что он специально упоминает, что не может предоставить простое объяснение, почему это так, т.е. почему два опорных элемента должны быть лучше одного. В чем-то лучше, в чем-то хуже, разные факторы балансируют друг против друга и в итоге - согласно Ярославскому - два опорных выигрывают, но простой картинки нет.

P.S. Обнаружилась заявка на патент 2005-го года, "Multiple Pivot Sorting Algorithm". Основная идея та же, но опорных точек там выбирают много (от 3 до 7), и их надо в свою очередь сортировать между собой. Раскладка элементов по подмассивам требует сравнения каждого элемента со всеми опорными меньше его. Мне это кажется довольно дорогим удовольствием: требует намного больше сравнений, чем в теоретически оптимальном двоичном поиске среди отсортированных опорных элементов, каковой реализовать в данном случае невозможно без дополнительного копирования подмассивов. Поэтому мне кажется маловероятным, что этот алгоритм с большим числом опорных точек лучше алгоритма Ярославского; а в частном случае двух опорных точек он точно хуже его. Но никаких проверок я не запускал.
(deleted comment)

Date: 2009-09-12 04:44 pm (UTC)
From: [identity profile] lykac.livejournal.com
Image
http://ru.wikipedia.org/wiki/Quicksort

Date: 2009-09-12 04:07 pm (UTC)
From: [identity profile] deadkittten.livejournal.com
Возможно тут дело аналогично многоленточной сортировке -- увеличение числа лент увеличивает один вид затрат, уменьшение -- другой. И основной вопрос, какое соотношение окажется оптимальным...

Date: 2009-09-14 09:12 am (UTC)
From: [identity profile] doktor-gradus.livejournal.com
Тогда, очевидно, нужно каким-то образом оценивать входную выборку на предмет выбора оптимального алгоритма сортировки. Хмм...

Date: 2009-09-12 04:24 pm (UTC)
From: (Anonymous)
Сравнивать теперь надо не с одним опорным элементом, а с двумя, то есть количество сравнений на один проход проход получается в среднем в полтора раза больше, чем в классическом алгоритме. Почему общее число сравнений в конечном итоге будет таким же, а не в 1.5 раза больше? Неочевидно ;)

Date: 2009-09-12 05:14 pm (UTC)
From: [identity profile] avva.livejournal.com
Потому что уровней рекурсии меньше. На каждом уровне рекурсии мы сравниваем (игнорируя мелкие оптимизации) каждый элемент с опорным в классическом алгоритме, или, как вы верно заметили, в полтора раза больше в новом. Но в классическом число уровней рекурсии равно логарифму по основанию 2 от начального размера, а в новом логарифму по основанию 3. С трудом вспомнив формулы из старших классов школы ;), заметим, что log_2(x)/log_3(x) = log_2(3) = примерно 1.58, что довольно близко к 1.5...

(no subject)

From: (Anonymous) - Date: 2009-09-12 06:40 pm (UTC) - Expand

Date: 2009-09-12 04:35 pm (UTC)
From: [identity profile] mudak.livejournal.com
Подозреваю, что оптимальным числом подмассивов должно быть e, но обосновать не могу.

Date: 2009-09-12 06:52 pm (UTC)
From: [identity profile] old-radist.livejournal.com
Красивая мысль!

Date: 2009-09-12 09:31 pm (UTC)
From: [identity profile] scolar.livejournal.com
Я попытку это обосновать читал в какой-то статье на младших курсах, то есть примерно 20 лет назад. Теперь уже и не вспомню, конечно. Собственно, там это было под соусом что в любых алгоритмах "разделяй и властвуй" число e должно давать лучшие константы, но в практическом плане двойка куда удобнее тройки, а большой разницы ждать не стоит.

Date: 2009-09-12 04:46 pm (UTC)
From: [identity profile] spamsink.livejournal.com
Брусенцов поныне здравствующий должен очень радоваться - это подтверждение его идеи о превосходстве троичного над двоичным.

Date: 2009-09-12 04:49 pm (UTC)
From: [identity profile] lykac.livejournal.com
а популярны ли алгоритмы, которые учитывают архитектуру процессора, в частности длину конвейера и количество ядер?

Date: 2009-09-12 05:19 pm (UTC)
From: [identity profile] avva.livejournal.com
Распределение памяти по кэшам (L1/L2/L3) важнее, чем длина конвейера, и также играет роль, если используется параллельный алгоритм на нескольких ядрах. Но я не знаю никакого алгоритма, который бы стремился это специально учитывать; просто это может повлиять на то, насколько быстро работает данный последовательный или данный параллельный алгоритм. Под параллельным алгоритмом я имею в виду на практике какую-нибудь версию merge sort.

(no subject)

From: [identity profile] ygam.livejournal.com - Date: 2009-09-12 05:37 pm (UTC) - Expand

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2009-09-12 05:52 pm (UTC) - Expand

(no subject)

From: [identity profile] ygam.livejournal.com - Date: 2009-09-12 06:00 pm (UTC) - Expand

(no subject)

From: [identity profile] cmm.livejournal.com - Date: 2009-09-12 05:40 pm (UTC) - Expand

Date: 2009-09-12 05:59 pm (UTC)
From: [identity profile] ygam.livejournal.com
Количество ядер - это простая параллелизация. Если мы исполняем алгоритм поиска на 8ядерном процессоре, то можно разбить дерево приблизительно на 8 поддеревьев, и поиск по каждому поддереву поручить одному ядру.

(no subject)

From: [identity profile] lykac.livejournal.com - Date: 2009-09-12 06:42 pm (UTC) - Expand

(no subject)

From: [identity profile] doktor-gradus.livejournal.com - Date: 2009-09-14 09:15 am (UTC) - Expand

Date: 2009-09-12 05:29 pm (UTC)
From: [identity profile] ygam.livejournal.com
По-моему, у Сёджвика в Algorithms in C в главе о быстрой сортировке говорится про несколько опорных точек. Я свой экземпляр лет 10 назад подарил, и не могу посмотреть.

Date: 2009-09-12 05:52 pm (UTC)
From: [identity profile] avva.livejournal.com
Нет, в _Algorithms in C_ про это ничего нет, я сейчас проверил.

(no subject)

From: [identity profile] ygam.livejournal.com - Date: 2009-09-12 05:56 pm (UTC) - Expand

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2009-09-12 05:59 pm (UTC) - Expand

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2009-09-12 07:21 pm (UTC) - Expand

(no subject)

From: [identity profile] saccovanzetti.livejournal.com - Date: 2009-09-12 08:02 pm (UTC) - Expand

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2009-09-12 08:06 pm (UTC) - Expand

(no subject)

From: [identity profile] scolar.livejournal.com - Date: 2009-09-12 09:34 pm (UTC) - Expand

Date: 2009-09-12 05:34 pm (UTC)
From: [identity profile] http://users.livejournal.com/_rowan_tree_/
Идея настолько проста, что никому в голову не пришло посчитать и проверить. Забавно.

Date: 2009-09-12 06:16 pm (UTC)
From: [identity profile] getman.livejournal.com
Мне кажется что оптимальное число точек должно быть функцией от размера массива, чтобы рандомальное дерево рекурсии было более-менее сбалансированным.

Date: 2009-09-12 06:45 pm (UTC)
From: [identity profile] cousin-it.livejournal.com
Да, Ярославский молодец - не поленился проверить интуитивно очевидное утверждение и в результате опроверг его. В мои математические годы мы называли подобные ситуации "приз за научную добросовестность".

Date: 2009-09-12 07:22 pm (UTC)
From: [identity profile] avva.livejournal.com
Я меж тем уже не уверен, что он прав. Но все равно молодец, что копает, конечно.
From: [identity profile] gianthare.livejournal.com
Сам алгоритм, как я у него глянул, слегка муторней, т.е. из головы не напишешь.
Интересно, сколько времени займет у этого нового варианта заменить везде квиксорт (אם בכלל).

Off

Date: 2009-09-12 07:42 pm (UTC)
From: [identity profile] vasja-iz-aa.livejournal.com
А Вы не могли бы посоветовать какую-нибуть лучшую книгу вместо этой? Лучше бы без использования Пролога или других экзотических языков, но это не критично.
http://a-future.ru/sistemy-iskusstvennogo-intellekta-zh-l-lorer.html

Re: Off

Date: 2009-09-12 08:08 pm (UTC)
From: [identity profile] avva.livejournal.com
У меня очень мало настоящих знаний по AI. По моему опыту, умные люди в этой области неизбежно предлагают книгу Норвига, и вообще говоря книги у него обычно замечательные (но именно эту я не читал). На ее сайте есть несколько глав, по которым можно судить об общем стиле/уровне книги: http://aima.cs.berkeley.edu/

Re: Off

From: [identity profile] vasja-iz-aa.livejournal.com - Date: 2009-09-12 08:44 pm (UTC) - Expand

Re: Off

From: [identity profile] avva.livejournal.com - Date: 2009-09-12 10:02 pm (UTC) - Expand

Re: Off

From: [identity profile] vasja-iz-aa.livejournal.com - Date: 2009-09-12 10:37 pm (UTC) - Expand

Re: Off

From: [identity profile] avva.livejournal.com - Date: 2009-09-13 12:50 am (UTC) - Expand

Date: 2009-09-12 09:48 pm (UTC)
From: [identity profile] itman.livejournal.com
Я когда увидел про этот алгоритм: моя первая мысль была, а какая зависимость числа сравнения и обменов от количества опорных элементов. Ярославский показал, что с двумя опорными векторами лучше (и это очевидно его заслуга, а не изобретение нового алгоритма, которые уже давно придумали). Но что будет в случае трех? Неужели хуже, чем с двумя?

Date: 2009-09-13 12:45 am (UTC)
From: [identity profile] avva.livejournal.com
Полагаю, что хуже - написал в апдейте к записи, почему так думаю. Но не проверял.

(no subject)

From: [identity profile] itman.livejournal.com - Date: 2009-09-14 05:30 pm (UTC) - Expand

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2009-09-14 05:33 pm (UTC) - Expand

(no subject)

From: [identity profile] itman.livejournal.com - Date: 2009-09-14 05:38 pm (UTC) - Expand

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2009-09-14 06:03 pm (UTC) - Expand

Date: 2009-09-12 11:05 pm (UTC)
From: [identity profile] febb.livejournal.com
Очень интересно!
А я вот как-то выдумал алгоритм в несколько раз быстрее квиксорта
для массивов строк.
Наверное он похож на алгоритм Седжвика, но мне кажется должен быть быстрее.
Идея такая:
Рекурсивно, начиная со старшего байта:
1) вычисляем гистограмму встречающихся байт и сортируем на 256 кусков
в один проход
2) для каждого из 256 покусков повторяем 1) для 2го байта и т.д.

Конечно для ограничения вырождения алгоритм нужно усложнить.
Но вот в самом примитивном уровне как он выглядит на С++:



void ByteSort(char ** data, size_t Num, size_t size, size_t offset=0)
{
size_t i, S[256], // starting index per group
H[256]; // (histogram) number of elements in group
// init historgram:
memset(H, 0, sizeof(H));
// 1st path: make historgram of byte values:
for(i=0; i < Num; i++)
++H[ data[i][offset] ];
// calculate staring index positions:
size_t s = 0;
for(i=0; i < 256; i++)
{ S[i] = s; s += H[i]; }
// sorting by regrouping data:
char ** ds = // array of sorted elements
new char * [ Num ]; // alocate memory for large groups
for(i=0; i < Num; i++)
{
char * d = data[i];
ds[ S[ d[offset] ]++ ] = d; // increment current position and copy element
}
memcpy(data, ds, sizeof(*data)*Num); // copy sorted array back
delete [] ds; // free mem
// make starting indexes again:
s = 0;
for(i=0; i < 256; i++)
{ S[i] = s; s += H[i]; }
// sort recurecively all the groups:
if(--size)
{
++offset;
for(i=0; i < 256; i++)
if(H[i] > 1)
ByteSort(data + S[i], H[i], offset, size);
}
}

Мне интересно, кто-нибудь теоретически может оценить, насколько он быстрее?
По тестам со случайными массивами работает раз в 10 быстрее квиксорта.
Плохие случаи я не исследовал.

(no subject)

From: [identity profile] avva.livejournal.com - Date: 2009-09-13 12:11 am (UTC) - Expand

(no subject)

From: [identity profile] febb.livejournal.com - Date: 2009-09-13 12:14 am (UTC) - Expand

(no subject)

From: [identity profile] secondary-tea.livejournal.com - Date: 2009-09-13 02:26 pm (UTC) - Expand

Date: 2009-09-13 02:30 pm (UTC)
From: [identity profile] secondary-tea.livejournal.com
Я писал сортировку с двумя опорными точками четыре года назад. Любителей изобретать велосипед меньше не становится...

Date: 2009-10-07 06:44 pm (UTC)
From: [identity profile] brno.livejournal.com
Давно уже работы своих студентов сортирую по алфавиту в три-четыре стопки квиксортом; первый год мучался пузырьком, хи-хи. Кажется, мне даже проще проще сравнивать с двумя-тремя опорными точками, чем с одной, лучше в голове помещается.

Date: 2010-12-20 06:02 am (UTC)
From: [identity profile] vasionok.livejournal.com
по описанию похоже на специальный случай sample sort. Sample sort делает тоже самое, но с произвольным, заранее заданным количеством пивотов. Суть конечно не в том, что он делает меньше сравнений - удивительно, что всё ещё начинает анализ алгоритмов с подсчёта количества логических операций, - а в том, что он более эффективно использует кэш.

December 2025

S M T W T F S
  123 4 56
78 9 10 11 1213
1415 1617181920
21 22 23 24 2526 27
28293031   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Dec. 29th, 2025 10:11 am
Powered by Dreamwidth Studios