Crab & Developer
Developer Developer
Привет, Краб, я тут ковырялся с оптимизацией сортировки по остаткам для больших объёмов данных. Хотел бы узнать, как ты думаешь, какой подход будет самым эффективным для ключей из целых чисел фиксированной ширины?
Crab Crab
Интересный проект! Сортировка методом просадки может быть быстрее быстрой сортировки на больших данных, если оптимизировать количество проходов. Для чисел фиксированной ширины используй фиксированное количество проходов, равное размеру слова, делённому на ширину цифры. Пусть ширина цифры будет степенью двойки, чтобы использовать битовые маски и сдвиги вместо деления. И ещё, используй счётные массивы размером 2 в степени ширины цифры; если это слишком много памяти, разбей на два прохода. Заранее выделяй память для счётных массивов и выходного буфера, чтобы избежать перераспределений. И попробуй схему с двумя корзинами для небольших счётчиков: если диапазон в корзине очень маленький, можно переключиться на сортировку вставками, чтобы уменьшить постоянный множитель. Так и кеш будет работать быстрее, и накладные расходы минимальны.
Developer Developer
Отличные замечания, Крэб. Сначала займусь оптимизацией работы с битовой маской – деление просто убивает производительность на современных процессорах. По поводу этой ухватёнки с двумя бакетами – убедись, что порог настроен правильно; обычно 32 элемента вполне достаточно, но я попробую 64, чтобы посмотреть, поможет ли выравнивание по строкам кэша. И еще, проверь, чтобы массив счетчиков оставался в L1; если он вытесняется, все замедляется. Прогоню тест производительности против хорошо оптимизированной быстрой сортировкой и посмотрю. Спасибо за план.
Crab Crab
Звучит неплохо—оставляй массив счетчиков на 256 или 512 ячеек, чтобы он помещался в L1. По поводу порога в 64 элемента, следи за ошибками предсказания ветвлений; иногда меньшее значение даёт более плавное конвейерирование. Удачи с бенчмарком; настоящий успех приходит, когда размер данных намного превышает накладные расходы дополнительных проходов. Не забывай поддерживать профилирование в порядке.
Developer Developer
Отлично, я зафиксирую массив счётчиков на 512, чтобы наверняка. Добавлю небольшой профилировщик, который будет отслеживать ошибки предсказания ветвлений для отсечки в 64 элемента; если конвейер начнёт тормозить, уменьшу до 32. И настрою небольшой скрипт, чтобы увеличить размер данных до 10 гигабайт, чтобы дополнительные проходы не доминировали. Спасибо, что предупредил.
Crab Crab
Похоже, договорились. Только следи, чтобы массив из 512 элементов не залез в L2 на самом медленном ядре. Если счётчики неверных предсказаний начнут расти – вернись к 32 и, может, сделай небольшую таблицу для быстрого поиска, чтобы избежать ветвлений. Удачи с этим запуском на 10 гигабайт.
Developer Developer
Проверю давление L2, потом, если будет сбой в ветке, откачу на 32 и добавлю небольшую таблицу. Следующий запуск – 10 гигабайт.