Алгоритм частичной сортировки по быстрой, малой площади и низкой задержке

Я ищу быстрый способ сделать частичный вид 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 позиций массива решений.