Это длинный текст. Пожалуйста, потерпите меня. Вопрос сводится к следующему: Есть ли работоспособный алгоритм радикальной сортировки на месте ?
Предварительные
У меня есть огромное количество небольших строк фиксированной длины , в которых используются только буквы «A», «C», «G» и «T» (да, вы уже догадались : DNA ), которую я хочу отсортировать.
В данный момент я использую std::sort
, который использует introsort во всех распространенных реализациях STL . Это работает довольно хорошо. Однако я убежден, что radix sort идеально подходит для моей поставленной задачи и на практике должен работать намного .
Подробнее
Я проверил это предположение с очень наивной реализацией, и для относительно небольших входных данных (порядка 10000) это было правдой (ну, по крайней мере, более чем в два раза быстрее). Тем не менее, время выполнения ужасно ухудшается, когда размер проблемы становится больше ( N > 5 000 000).
Причина очевидна: радикальная сортировка требует копирования всех данных (на самом деле, не раз в моей наивной реализации). Это означает, что я поместил ~ 4 ГиБ в мою основную память, что, очевидно, снижает производительность. Даже если это не так, я не могу позволить себе использовать столько памяти, поскольку размеры проблем на самом деле становятся еще больше.
Варианты использования
В идеале этот алгоритм должен работать с любой длиной строки от 2 до 100, для ДНК, а также для ДНК5 (которая допускает дополнительный подстановочный знак «N») или даже для ДНК с IUPAC коды неоднозначности (в результате получается 16 различных значений). Тем не менее, я понимаю, что все эти случаи не могут быть охвачены, поэтому я доволен любым улучшением скорости, которое я получаю. Код может динамически решать, какой алгоритм отправить.
Research
К сожалению, статья в Википедии о радикальной сортировке бесполезна. Раздел о варианте на месте - полная чушь. Секция NIST-DADS на радикальной сортировке почти не существует. Есть многообещающая статья под названием Эффективная адаптивная сортировка по радикалам на месте , в которой описывается алгоритм «MSL». К сожалению, эта статья тоже разочаровывает.
В частности, есть следующие вещи.
Во-первых, алгоритм содержит несколько ошибок и оставляет много необъяснимых. В частности, он не детализирует рекурсивный вызов (я просто предполагаю, что он увеличивает или уменьшает некоторый указатель для вычисления текущих значений сдвига и маски). Кроме того, он использует функции dest_group
и dest_address
без определения. Я не вижу, как их эффективно реализовать (то есть в O (1); по крайней мере, dest_address
не тривиально).
И наконец, что не менее важно, алгоритм достигает на месте, меняя индексы массива с элементами внутри входного массива. Это очевидно работает только на числовых массивах. Мне нужно использовать его на строки. Конечно, я мог бы просто прокрутить строгую типизацию и продолжить, предполагая, что память будет терпеть мое хранение индекса, которому он не принадлежит. Но это работает только до тех пор, пока я могу сжать свои строки в 32-битной памяти (при условии 32-битных целых). Это всего 16 символов (на данный момент давайте проигнорируем, что 16> log (5 000 000)).
Другой документ одного из авторов не дает точного описания вообще, но он дает время выполнения MSL как сублинейное, что совершенно неверно.
Напомним : Есть ли надежда найти работающую эталонную реализацию или хотя бы хороший псевдокод / описание работающей радикальной сортировки на месте, которая работает на строках ДНК?