|
|
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
Прав был Шарахов, когда 4 года назад в своём блоге сказал "быстрая сортировка обладает какой-то мистической силой, заставляя снова возвращаться к ней". В битве за удобством и скоростью мне удалось достичь определённых успехов и сегодня я поделюсь результатами своего труда, но сперва объясню, чем вообще вызвана необходимость доработать сортировку. Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 1) По долгу службы мне периодически приходится обрабатывать внушительные объёмы данных и совсем не редкая операция - сортировка. В модуле Classes в своё время я нашёл реализацию и достаточно долго использовал её (листинг выше). Но в реальных условиях нужно сортировать не указатели, а структуры. Периодически приходилось создавать вспомогательный массив указателей, инициализировать и позже вызывать QuickSort. В конечном счёте потребовалось простое решение, при помощи которого можно оперативно "создать" требуемую сортировку. 2) Конечно напрашивается решение - использовать шаблоны. Но в Delphi7 шаблонов нет, а современные дженерики обладают существенным рядом недостатков, о которых поговорим позже. 3) В теории глубина рекурсии в QuickSort в худшем случае - равна N. В Delphi реализации ситуация оптимизируется, но не решается кардинально. А значит в зависимости от набора данных вполне существует вероятность, что скажем при сортировке миллиона элементов произойдёт переполнение стека. Ситуация усугубляется тем, что на платформе x64 стек в рекурсиях расходуется значительно быстрее, чем на x86 и ARM. Мне же удалось реализовать решение, которое не только не приведёт к переполнению стека, но и затратит в худшем случае 1кб на платформе x64. 4) Я обнаружил, что львиную долю времени сортировки занимает вызов калбека сравнения. Необходимость в нём на практике возникает не всегда. Мы часто сравниваем 1-2 поля, причём числовых, а значит реализовав сравнение вручную или вызвав inline оператор (надеюсь такие есть) - мы существенно повысим производительность сортировки. К сожалению дженерики не позволяют использовать операторы сравнения, а функции-компараторы гарантированно дают просадку производительности (что отлично видно на тесте с Integer). К слову привычные компараторы тоже используются неэффективно. В своё время Sha посвятил небольшой раздел правильному сравнению Integer с громким названием "Самая быстрая на Земле". Но в умных реализациях сортировки на С++ используется оператор < (LessThan), которого достаточно, и который существенно упрощает и сокращает время сравнения. Код: pascal 1. 2. 3. 4. 5) Вас ожидает сюрприз - если станете сортировать строки, варианты, интерфейсы, динамических массивы, замыкания или структуры их содержащие. Алгоритм быстрой сортировки минимум в двух местах предполагает чтение и запись структур. А при каждом копировании таких данных происходит невидимая рутина по инициализации и финализации данных. Не говоря уже о невидимом блоке try/finally, призванном подчищать данные по выходу из функции. Существует способ обойти внутреннюю рутину через копирование массива байт, но в рамках дженериков реализовать такой подход невозможно. В итоге при неумелой сортировке строк/массивов/структур/etc вас всегда ожидает просадка производительности. Что кстати легко заметить в тесте для строк. В обоих случаях используется стандартный RTL компаратор строк, но буферизируются элементы по разному. Код: pascal 1. 2. 3. 6) Одна из оптимизаций - сортировка вставками для малых (под)массивов. Реализацию брал и оптимизировал у Шарахова. 7) Ну и наконец оптимизации на низком уровне. Поскольку конечное время работы зависит от объёма исполненных тактов, а количество регистров крайне мало - путём титанических усилий, мне всё-таки удалось выжать из компилятора Delphi максимум :) Собственно всё. Используйте кому нужно. Скопируйте функцию и замените <T> на ваш тип. Несмотря на страшный вид функций, бинарный размер у них примерно равен дженерик-реализациям. Для сортировки Integer порядка 288 байт если не ошибаюсь. Ссылка: http://webfile.ru/8ea97d85dff9b007d66aef7b251f7e1d ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.08.2014, 20:46:25 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
Ох не говори про него. Несколько лет назад для наших библиотек я тоже написал вариацию. В ней нет ни одной ассемблерной инструкции, а процедура сравнения передается как параметр (а не жестко зашита в алгоритм). Результаты на моем компе: QuickSort(Integer) test: Generics QuickSort (standard)... 3198ms. Asm QuickSort... 1544ms. Smart QuickSort... 1248ms. DX QuickSort... 733ms. Press Enter QuickSort(String) test: Generics QuickSort (standard)... 13650ms. Smart QuickSort... 5258ms. DX QuickSort... 2995ms. Press Enter Хинт. Юзай многопоточность, раз уж у тебя такие "тяжелые" задачи ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.08.2014, 21:49:41 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
white_nigger, твои результаты за счет использования кучи ядер, или DX реализация однопоточная? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.08.2014, 22:06:26 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
Ессно, выигрыш получается при использовании многопоточности, там главная хитрость, определить когда её можно использовать :). А так даже на древних 2х-ядерных процах есть ускорение. Причем зависимость нелинейная, сказываются особенности алгоритмов ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.08.2014, 22:14:40 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
SOFT FOR YOU, Какие условия использования кода? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.08.2014, 22:27:59 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
white_nigger красавчик! тока у меня не настолько большие объёмы. тысяч 10 максимум. но часто. распараллеливание думаю мало поможет. но скинь сорсы посмотреть. p.s. у меня тоже ассемблера нет ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.08.2014, 23:43:18 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
asviridenkovКакие условия использования кода? любые :)) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 00:27:50 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
SOFT FOR YOUasviridenkovКакие условия использования кода? любые :)) Тогда есть смысл посмотреть на код! Ты раз такой любитель оптимизации, то обратил бы внимание на другой аспект. У меня вот гораздо чаще возникают претензии к скорости поиска а не сортировки. С появлением TDictionary стало получше, но все равно говорят что там до оптимальности очень далеко, особенно в плане скорости работы хэш-функции. Вот если бы ты написал что-то компилируемое во всей линейке XE2+ 32/64 всеплатформенное и работающее быстрее, было бы круто. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 00:48:22 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
asviridenkov быстрее хешей ничего нет у меня есть наработки, которых мне хватает, но они под x86 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 00:53:27 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
SOFT FOR YOU asviridenkov быстрее хешей ничего нет у меня есть наработки, которых мне хватает, но они под x86 Да это понятно. Там хеш-функция не оптимальная. Под х86 не интересно. Нужна на дженериках и всеобщая ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 00:56:29 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
asviridenkov напишу за 10 тыщ если нужно :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 01:16:55 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
SOFT FOR YOUу меня тоже ассемблера нетПросто я в своё время тоже просматривал решения Шарахова, а у него там самые быстрые были как раз ассемблерные версии. А вообще я отписался здесь исходя из того, что много людей не всегда верно подходят к задачам оптимизации. За долгие годы работы в ДХ я косвенно общался с многими программистами (а не энд-юзерами как многие тут) и не раз это наблюдал. Чаще всего реальный прирост дает не попытка сэкономить десяток-другой ассемблерных команд, а изменение архитектуры или пересмотр алгоритмов. PS: Поскольку свой код публиковать не имею права, подскажу что в инете можно найти подобные решения. По сути надо исходные данные разбить на блоки и в потоках выполнить QuickSort для каждого. А потом также используя потоки смержить результаты. Правда, как замечал ранее, перед этим надо убедиться что процедура сравнения потокобезопасна ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 01:35:58 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
SOFT FOR YOUтысяч 10 максимум. но часто. распараллеливание думаю мало поможет. но скинь сорсы посмотретьПоможет. Обычно процедура сравнения более тяжелая чем простое сравнение чисел (для этого случая вообще лучше поразрядную сортировку использовать). А если у тебя есть наши продукты, то реализацию можешь посмотреть в классе TdxMultithreadedSort модуль dxThreading. Также распараллеливанием легко ускоряется поиск в неотсортированных данных (TList, TStrings) и пакетные обработки ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 01:46:57 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
white_nigger а почему кстати зависимость нелинейная? а поразрядная сортировка да, рулит :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 02:12:37 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
asviridenkovС появлением TDictionary стало получше, но все равно говорят что там до оптимальности очень далеко, особенно в плане скорости работы хэш-функции. Вот если бы ты написал что-то компилируемое во всей линейке XE2+ 32/64 всеплатформенное и работающее быстрее, было бы круто. Для хэш-функции словаря важна не только скорость, но и распределение, в этом плане Дженкинс очень годное решение. Я их перепробовал штук 15, наверное, на трех наборах данных: словаре английских слов, массиве GUID'ов и строковом представлении инкрементируемого счетчика format('index%d', [counter]). Впрочем, для конкретных типов ключей можно задействовать собственные хэши, достаточно создать словарь с кастомным компарером. Например для строк очень хорошую скорость и распределение дает функция Роберта Седжвика, я использую её в своем "аналоге" словаря (по скорости поиска уделываю его раза в полтора [можно еще ускорить, но структура данных из-за поддержки индексации сильно не cache friendly], по добавлению более двух раз, по потреблению памяти экономичнее на четверть). У словаря по-дурацки сделано распределение памяти при заранее заданной вместимости (capacity), оно всегда получается примерно на треть больше необходимого. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 03:33:12 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
Kazantsev Alexey По моему люди сильно переоценивают значение хеш-функции. Во-первых, даже самая крутая хеш-функция не обезопасит тебя от хеш-промахов. А во-вторых, люди мутят такие функции, что себестоимость её вызова значительно выше обрабатываемых промахов. Значительно важнее организация хеш-таблицы и менеджмент памяти. В теории размер таблицы должен быть простым числом (для лучшего распределения), на практике размер должен быть степенью двойки, ибо операция вычисления индекса через остаток от деления убивает к чертям весь профит. Ну и стандартному менеджеру памяти можно предпочесть альтернативный, потому что структуры имеют одинаковый размер и заточка на многопоточность не нужна (если конечно контейнер не с многопоточным доступом). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 09:40:40 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
SOFT FOR YOUпочему кстати зависимость нелинейная? я как-то пробовал выпытать оценку по ихнему варианту (однопоточному) но в итоге нашару подобрал формулу к-я давала б.м. подходящий мне вариант white_niggerя отписался здесь исходя из того, что много людей не всегда верно подходят к задачам оптимизацииугу, хорошо бы иногда вместо того чтоб оптимайзить сортировки (что конечно само по себе и похвально) элементарно вычистить реализацию базовых вещей дабы избегать попросту ненужных (но весьма дорогостоящих) операций как например в Q515958, Q516328, Q515220 и т.п. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 10:48:05 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
SOFT FOR YOUтока у меня не настолько большие объёмы. тысяч 10 максимум. но часто. распараллеливание думаю мало поможета у них там такой оверхед на самом контейнере и датаконтроллере что многопоточность оказалась реальным подспорьем. а так ср-вами например датасета сортировка даже в однопоточном варианте в разы быстрее фурычит ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 10:52:47 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
vavanугу, хорошо бы иногда вместо того чтоб оптимайзить сортировки (что конечно само по себе и похвально) элементарно вычистить реализацию базовых вещей дабы избегать попросту ненужных (но весьма дорогостоящих) операций как например в Q515958, Q516328, Q515220 и т.п.Или спроектировать приложение нормально, чтоб не было нужды тащить сотни тысяч записей на клиент. Это даст гораздо более ощутимый прирост быстродействия. К тому же не всегда есть возможность, избавиться от двойных вызовов, или пересчетов. Ты просто не видишь полной картины и не представляешь всех возможных сценариев использования. Кстати зачем тебе в Q515958 одновременно и лочение грида и лочение датасета? Если правильно помню, там простым переставлением порядка локов можно было сэкономить лишний пересчет ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 12:56:07 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
white_niggerИли спроектировать приложение нормально"расскажи моей бабуле про ее вставные зубы" (С) серьезно, не учите меня жить и я тогда не скажу куда вам следует пройти. разработчику либы невдомек как ее юзают конечные пользователи а отсюда он просто обязан минимизировать оверхэд и приложить максимум усилий к оптимизации. а в данных случаях скорее даже к избеганию "пессимизации" white_niggerТы просто не видишь полной картины и не представляешь всех возможных сценариев использованияугу, я как раз об этом выше, не представляете. а лично меня заботят исключительно дата-аварные варианты, с иными изголяйтесь как хотите - мне поровну white_niggerзачем тебе в Q515958 одновременно и лочение грида и лочение датасета? Если правильно помню, там простым переставлением порядка локов можно было сэкономить лишний пересчетувы, не всегда достаточно лочить лишь датасет, иногда приходится и грид а то еще и датаконтроллер отдельно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 13:14:28 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
vavanразработчику либы невдомек как ее юзают конечные пользователиХорошо подумал прежде чем написать? За эти годы просмотрел сотни если не тысячи юзеркейсов, причем некоторые не приснились бы и в кошмарах. А тому кто постоянно недоволен нашими продуктами, мы можем предложить вернуть деньги, дабы бедняга не "кушал кактусы" если уж наш продукт его так не устраивает, и спокойно писать фичи которые реально востребованы ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 13:45:40 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
Сорри за офтоп. Обычно я не обсуждаю такие вещи и не перехожу на личности, видать накипело. Завязываю... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 13:48:08 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
white_niggerХорошо подумал прежде чем написать?а думаешь брякнул как всегда бездумно? white_niggerтому кто постоянно недоволен нашими продуктами, мы можем предложить вернуть деньгибуду чрезвычайно признателен если сделаете это по окончании очередного сабскрипшна к-й я продлил пару недель назад. собсно можно было бы и к зиме-весне (когда выйдет последний выпуск под 2007) но техдир заявил что поддержка крайней версии будет длиться еще год ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 14:18:52 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
vavanбуду чрезвычайно признателен если сделаете это по окончании очередного сабскрипшна ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 15:04:53 |
|
||
|
О QuickSort не говори
|
|||
|---|---|---|---|
|
#18+
white_niggerпо окончании?ну разумеется. поясню что все что было выложено за многолетнее обновление сабскрипшна и собсно саппорт к возврату и не ожидается white_niggerа это... не треснет?ну я за язык никого не тянул. или это было неподкрепленное предложение? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.08.2014, 15:24:58 |
|
||
|
|

start [/forum/topic.php?fid=58&msg=38718145&tid=2042048]: |
0ms |
get settings: |
10ms |
get forum list: |
16ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
193ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
64ms |
get tp. blocked users: |
1ms |
| others: | 218ms |
| total: | 521ms |

| 0 / 0 |
