Быстрая реализация алгоритма для сортировки очень маленького списка

Это проблема, с которой я столкнулся очень давно. Я подумал, что могу спросить у вас ваши идеи. Предположим, у меня очень маленький список чисел (целых чисел), 4 или 8 элементов, которые нужно быстро отсортировать. какой будет лучший подход / алгоритм?

мой подход заключался в использовании функций max / min (10 функций для сортировки 4 чисел, без веток, iirc).

// s(i,j) == max(i,j), min(i,j)
i,j = s(i,j)
k,l = s(k,l)
i,k = s(i,k) // i on top
j,l = s(j,l) // l on bottom
j,k = s(j,k)

Думаю, мой вопрос больше касается реализации, а не типа алгоритма.

На этом этапе он становится несколько зависимым от оборудования, поэтому предположим, что 64-битный процессор Intel с SSE3.

Спасибо


person Anycorn    schedule 01.05.2010    source источник
comment
Я задал в основном тот же вопрос, но с более конкретным контекстом (реализация C, массивы из 6 целых чисел) и использовал регистр счетчика циклов для оценки производительности. Вы можете увидеть результаты здесь: stackoverflow.com/questions/2786899/   -  person kriss    schedule 10.05.2010
comment
связанные: Самый быстрый вид массива 6 int фиксированной длины   -  person Janus Troelsen    schedule 12.05.2013


Ответы (6)


Для таких небольших массивов вам, вероятно, следует изучить сети сортировки. Как вы можете видеть на этой странице, сортировку вставкой можно выразить как сеть сортировки. Однако, если вы заранее знаете размер массива, вы можете разработать оптимальную сеть. Взгляните на этот сайт, который поможет вам найти оптимальные сети сортировки для заданного размер массива (хотя оптимальный размер гарантирован только до размера 16, я считаю). Компараторы даже сгруппированы вместе для операций, которые могут выполняться параллельно. Компараторы по сути такие же, как ваша функция s (x, y), хотя, если вы действительно хотите, чтобы это было быстро, вы не должны использовать min и max, потому что тогда вы делаете в два раза больше необходимых сравнений.

Если вам нужен этот алгоритм сортировки для работы с широким диапазоном размеров, вам, вероятно, следует просто пойти с сортировкой вставкой, как предлагали другие.

person Justin Peel    schedule 01.05.2010
comment
Итак, древний ответ здесь, но я неверно истолковал концепцию оптимальной сети сортировки, когда впервые прочитал этот ответ, чтобы уточнить: оптимальная сеть сортировки на самом деле не использует минимальное количество компараторов! Сортировочные сети ограничены тем, что они всегда используют одно и то же фиксированное расположение компараторов; то есть, что нет разветвлений при принятии решения о том, какие элементы сравнивать. Это отлично подходит для аппаратных реализаций и GPGU, но это означает, что вам понадобится больше сравнений, чем строго необходимо, даже при довольно небольших размерах массива (я считаю, от 5 и выше). - person Eamon Nerbonne; 12.10.2018

Я вижу, у вас уже есть решение, использующее 5 сравнений (при условии, что s (i, j) сравнивает два числа один раз и либо меняет их местами, либо нет). Если вы будете придерживаться сортировки на основе сравнения, вы не сможете сделать это с помощью менее 5 сравнений.

Это можно доказать, потому что их 4! = 24 возможных способа заказать 4 номера. Каждое сравнение может сократить возможности только наполовину, поэтому с 4 сравнениями вы можете различить только 2 ^ 4 = 16 возможных порядков.

person mathmike    schedule 01.05.2010

Чтобы отсортировать небольшое количество чисел, вам нужен простой алгоритм, поскольку сложность увеличивает накладные расходы.

Самый эффективный способ сортировки, например, четырех элементов, - это разложить алгоритм сортировки до линейных сравнений, тем самым устраняя все накладные расходы:

function sort(i,j,k,l) {
  if (i < j) {
    if (j < k) {
      if (k < l) return [i,j,k,l];
      if (j < l) return [i,j,l,k];
      if (i < l) return [i,l,j,k];
      return [l,i,j,k];
    } else if (i < k) {
      if (j < l) return [i,k,j,l];
      if (k < l) return [i,k,l,j];
      if (i < l) return [i,l,k,j];
      return [l,i,k,j];
    } else {
      if (j < l) return [k,i,j,l];
      if (i < l) return [k,i,l,j];
      if (k < l) return [k,l,i,j];
      return [l,k,i,j];
    }
  } else {
    if (i < k) {
      if (k < l) return [j,i,k,l];
      if (i < l) return [j,i,l,k];
      if (j < l) return [j,l,i,k];
      return [l,j,i,k];
    } else if (j < k) {
      if (i < l) return [j,k,i,l];
      if (k < l) return [j,k,l,i];
      if (j < l) return [j,l,k,i];
      return [l,j,k,i];
    } else {
      if (i < l) return [k,j,i,l];
      if (j < l) return [k,j,l,i];
      if (k < l) return [k,l,j,i];
      return [l,k,j,i];
    }
  }
}

Однако код значительно увеличивается с каждым добавленным вами дополнительным элементом. Добавление пятого элемента увеличивает размер кода примерно в четыре раза. В восьми элементах это будет примерно 30000 строк, поэтому, хотя он по-прежнему наиболее эффективен, это большой объем кода, и вам придется написать программу, которая пишет код, чтобы сделать его правильным.

person Guffa    schedule 01.05.2010
comment
исходная программа использовала что-то вроде этого, но производительность была довольно низкой, я предполагаю, из-за проблем с ветвями - person Anycorn; 01.05.2010
comment
@aaa: Понятно ... Что ж, чтобы устранить все ветвления, вы можете провести все необходимые сравнения и объединить результаты в ключ и использовать его для получения массива индексов из предварительно рассчитанного словаря всех возможных результатов. - person Guffa; 01.05.2010
comment
Этот алгоритм хорош, но не оптимален: он может выполнять до 6 сравнений, в то время как оптимальный алгоритм не должен выполнять более 5 сравнений. - person Morwenn; 18.08.2015

Сортировка вставкой считается лучшей для небольших массивов. См. Быстрая стабильная сортировка небольших массивов (до 32 или 64 элемента)

person mathmike    schedule 01.05.2010
comment
Привет. Меня больше интересует подход к реализации - person Anycorn; 01.05.2010
comment
Я не уверен, что вы имеете в виду под подходом к реализации. Вы хотите обсудить ассемблерный код? - person mathmike; 01.05.2010
comment
не совсем так низко, но что-то, что будет показывать ветки / инструкции - person Anycorn; 01.05.2010
comment
Я реализовал сортировку вставкой на C ++ для встраиваемых платформ. Он оказался оптимальным по размеру скомпилированного двоичного файла во всех случаях, вероятно, потому, что оптимизатор смог распутать сортировку по сетям сортировки в тех случаях, которые были полезны (когда у вас есть список известного размера во время компиляции). - person Emil Vikström; 20.06.2017

Для такого небольшого набора данных вам нужен как можно более простой алгоритм. Скорее всего, подойдет и базовая Сортировка вставкой. как вы могли хотеть.

Потребуется больше узнать о системе, в которой он работает, сколько раз вам нужно выполнять такую ​​сортировку в секунду и т. Д., Но общее правило для небольших сортировок - сохранять простоту. Быстрая сортировка и тому подобное бесполезны.

person bwawok    schedule 01.05.2010
comment
привет, я написал некоторые пояснения. Я ищу больше идей для реализации - person Anycorn; 01.05.2010

Сортировочные сети могут быть легко реализованы в SIMD, хотя она начинает становиться некрасивой примерно при N = 16. Для N = 4 или N = 8 это был бы хороший выбор. В идеале вам нужно много небольших наборов данных для одновременной сортировки, то есть, если вы сортируете 8-битные значения, вам нужно, чтобы отсортировать как минимум 16 наборов данных - гораздо сложнее делать такие вещи по векторам SIMD .

См. Также: Самый быстрый вид массива int фиксированной длины 6

person Paul R    schedule 01.05.2010