Це довгий текст. Будь ласка, нехай зі мною. Зникла питання: чи є дієвий алгоритм сортування радіоактивних місць ?
Попередній
У мене величезна кількість невеликих рядків фіксованої довжини, які використовують лише літери "A", "C", "G" і "T" (так, ви вже здогадалися: ДНК ), які я хочу сортувати.
На даний момент я використовую, std::sort
який використовує інтросорт у всіх поширених реалізаціях STL . Це працює досить добре. Однак я переконаний, що сортування radix ідеально відповідає моїй проблемі, яка постає перед нами і повинна працювати набагато краще на практиці.
Деталі
Я перевірив це припущення з дуже наївною реалізацією, і для відносно невеликих вкладів (порядку 10 000) це було правдою (ну, принаймні, удвічі швидше). Однак час виконання погіршується безсильно, коли розмір проблеми збільшується ( N > 5 000 000).
Причина очевидна: radix сортування вимагає копіювання всіх даних (фактично не один раз в моїй наївній реалізації). Це означає, що я помістив ~ 4 Гб в основну пам'ять, яка, очевидно, вбиває продуктивність. Навіть якщо цього не сталося, я не можу дозволити собі використовувати стільки пам’яті, оскільки розміри проблем фактично стають ще більшими.
Використовуйте випадки
В ідеалі цей алгоритм повинен працювати з будь-якою довжиною рядка від 2 до 100, як для ДНК, так і для ДНК5 (що дозволяє отримати додатковий символ символу “N”) або навіть ДНК з кодами неоднозначності IUPAC (в результаті чого 16 різних значень). Однак я розумію, що всі ці випадки не можуть бути охоплені, тому я задоволений будь-яким покращенням швидкості, яку я отримую. Код може динамічно визначати, до якого алгоритму відправити.
Дослідження
На жаль, стаття у Вікіпедії про сортування radix марна. Розділ про місцевий варіант - це повний сміття. Розділ NIST-DADS на сортировці radix знаходиться поруч із неіснуючим. Існує багатообіцяючий документ під назвою « Ефективна адаптивна сортировка на місці», який описує алгоритм «MSL». На жаль, цей документ теж розчаровує.
Зокрема, є такі речі.
По-перше, алгоритм містить кілька помилок і залишає багато незрозумілих. Зокрема, він не деталізує виклик рекурсії (я просто припускаю, що він збільшує або зменшує деякий покажчик для обчислення значень поточного зсуву та маски). Крім того, він використовує функції dest_group
і dest_address
не даючи визначень. Я не бачу, як ефективно їх реалізувати (тобто в O (1); принаймні, dest_address
це не тривіально).
І останнє, але не менш важливе, алгоритм досягає місця на місцях шляхом заміни індексів масиву елементами всередині вхідного масиву. Це, очевидно, працює лише на числових масивах. Мені потрібно використовувати його на струнах. Звичайно, я міг би просто накрутити сильний набір тексту та йти вперед, припускаючи, що пам'ять буде терпіти моє зберігання індексу там, де йому не належить. Але це працює лише до тих пір, поки я можу втиснути свої рядки в 32 біти пам'яті (при 32-бітових цілих числах). Це всього 16 символів (давайте ігноруємо на той момент, що 16> log (5 000 000)).
Інший документ одного з авторів взагалі не дає точного опису, але він дає час виконання MSL як сублінійне, що виходить неправильним.
Для резюме : Чи є надія знайти реалізацію робочої довідки або хоча б хороший псевдокод / опис робочого сорту radix на місці, який працює на ДНК-рядках?