Алгоритм частичной сортировки по быстрой, малой площади и низкой задержке
Я ищу быстрый способ сделать частичный вид 81 числа. В идеале я ищу, чтобы извлечь самые низкие 16 значений (не обязательно, чтобы 16 были в абсолютно правильном порядке).
Целью этого является выделенное оборудование в FPGA - так что это немного сложно, так как я хочу, чтобы область результирующей реализации была как можно меньшей. Я посмотрел и реализовал алгоритм сортировки с нечетным четным слиянием, но я идеально ищу все, что может быть более эффективным для моих нужд (размер реализации торгового алгоритма для частичной сортировки, дающий минимум 16, не обязательно в порядке, в отличие от полный сорт)
Любые предложения были бы очень желанными
Большое спасибо
Ответы
Ответ 1
Это можно сделать в O(nlog_k)
времени, где в вашем случае n = 81 и k = 16. Это очень эффективно, когда вы имеете дело с большим количеством элементов, чем O(nlog_n)
.
Алгоритм:
- Создать структуру данных с максимальной кучей. Эта куча будет содержать верхнюю часть 16. Размер этой кучи не будет превышать 16 и имеет log (k) для вставки и удаления
- Итерации по списку n-чисел. Для каждого n:
- Если куча имеет менее 16 элементов, просто добавьте ее
- Если кучка имеет 16 элементов, сравните
n
с max от кучи (если она больше max, просто пропустите, если меньше max, удалите max
и добавьте n
.)
Таким образом, на каждой итерации вы отслеживаете наименьшие k-числа из текущей обрабатываемой части списка.
Ответ 2
Это похоже на ядро обработки сигналов. Трудно ответить на это, не зная точного потока данных в вашем дизайне. Любой алгоритм, использующий сортировку, имеет стоимость декодирования адреса, поскольку вам нужно будет писать и читать память из 81 элемента. Если эти данные хранятся в памяти, эта стоимость уже была оплачена, но если она находится в разных регистрах, то запись на них несет стоимость области.
Предполагая, что данные находятся в памяти, вы можете использовать сортировку пузырьков и принимать нижние 16 значений. В приведенном ниже коде предполагается двухпортовая память, но она может работать с одним портом, чередуя чтение и запись в каждом такте с использованием временного регистра для хранения значения записи и записи индекса. Это может быть не более эффективным с точки зрения площади всего 81 элемент памяти.
В качестве альтернативы исходная память может быть реализована как две однопортовые памяти с одним, имеющим нечетные индексы и другие четные индексы.
// Not working code
reg [15:0] inData [80:0]; // Must be two-port
reg [3:0] iterCount = 0;
reg [6:0] index = 0;
reg sorting;
always @(posedge clk)
begin
// Some condition to control execution
if(sorting)
begin
if(index == 80)
begin
// Stop after 16 iterations
if(iterCount == 15)
begin
sorting <= 0;
iterCount <= 0;
end
else
begin
iterCount <= iterCount+1;
index <= 0;
end
end
else
begin
// If this is smaller than next item
if(inData[index] < inData[index+1])
begin
// Swap with next item
inData[index+1] <= inData[index];
inData[index] <= inData[index+1];
end
index <= index + 1;
end
end
end
EDIT: если вы ограничены в задержках, разрешен только один тактовый домен и должен конвейер, проблема ограничивается выбором сети сортировки и ее сопоставлением с конвейером. Вы не можете использовать совместное использование ресурсов, поэтому область фиксируется с учетом вашей сортировочной сети.
- Выберите сортировочную сеть (битной, парный и т.д.) для N = 81 (не легко)
- Создайте диаграмму направленного потока данных, представляющую сортировочную сеть.
- Удалите все узлы, кроме тех, которые необходимы для выходов 66-81
- Определите задержку L одного сравнения node
- Используйте ALAP-планирование для назначения M узлов за такт, где M * L < 1/е
- Если планирование выполнено успешно, выполните код в HDL
Ответ 3
Если вы ищете общие алгоритмы, вы можете использовать версию Quicksort. Quicksort сортирует значения вокруг элемента сворачивания. Вы выбираете ось и сортируете массив. Затем вы получаете значения x < pivot и (n-x-1) более крупные. В зависимости от x вы выбираете один массив для продолжения обработки. Если x > 16, то вы знаете, что числа, которые вы ищете, все находятся в x-массиве, и вы можете продолжить их сортировку. Если нет, то вы знаете x самый низкий и теперь можете искать 16-х других в другом массиве рекурсивно.
Результирующие массивы quicksort не полностью отсортированы, вы только знаете, что они меньше или больше вашего стержня. Некоторая информация на wikipedia и документ.
Ответ 4
Возможно, измененный медианный выбор является опцией? В противном случае, можно ли просто искать минимум 16 раз?
Ответ 5
Сначала установите массив с 16 значениями. И используйте что-то вроде сортировки сортировки:
- Вы считаете, что первое значение является минимальным в массиве.
- Сравните значение первого элемента, во-вторых, пока вы не найдете число ниже.
- Возьмите это как новый минимальный и сравните его со следующими числами, пока не найдете число ниже, чем оно.
- Если вы закончили массив, то у вас есть минимальное количество, сохраните его в массиве и исключите из исходного массива и начните заново, пока не заполните 16 позиций массива решений.