C priority_queue кортежа медленный

#c #priority-queue

#c #приоритетная очередь

Вопрос:

Мне нужно обработать динамический отсортированный список событий на C . Каждое событие состоит из 3 переменных: время (используется для сортировки списка) и 2 других. Я обрабатываю события данных по событиям, беру первое в отсортированном списке (с меньшей переменной времени), обрабатываю его, а затем удаляю из списка. Во время обработки событий я также должен добавить другие в этот список, которые могут быть добавлены в любую позицию.

Я пытался использовать prioriy_queue composed by tuple ( std::priority_queue<tuple<double, int, int>, std::vector<tuple<double, int, int>>, greater<tuple<double, int, int>>> ) , значение double — это переменная времени, используемая для сортировки списка, а целые числа — другие переменные, полезные для обработки. Это работает, он сохраняет список отсортированным по времени, я могу легко добавлять новые события и удалять первое, и мне просто нужно получить доступ к первому (с меньшим значением времени).

Но это занимает много времени. Большая часть времени, затрачиваемого моей программой, используется для добавления и удаления элементов в мой список. Существуют ли другие альтернативы, кроме приоритетной очереди? Использование tuple<double, int, int> , вероятно, не самый лучший способ и должно сильно повлиять, есть ли другие альтернативы?

Комментарии:

1. Сколько элементов в очереди максимум?

2. Это может значительно различаться. Иногда оно может превышать миллион элементов, а в остальное время приближаться к пятидесяти тысячам или меньше.

Ответ №1:

std::priority_queue Это, по сути, куча, lg2 N push и pop. Обратите внимание, что для миллиона элементов, которые будут равны 20 тыс. M, K малой константе, M обращений к памяти. Использование памяти 8 МБ для одного ядра, поэтому время для обновления до процессора, который предоставляет L3 доступ по крайней мере к такому объему памяти.

Это может быть улучшено до lg lg N (эквивалент Thorup) с некоторыми усилиями, но могут быть более простые варианты.

Если существует много временных коллизий, то кортеж не является правильной структурой.

Что-то вроде

 struct item {
  double time;
  int first, second;

  operator>(const item amp; other) const {
    return time > other.time;
  }
};

using pQueue = std::priority_queue<item, std::vector<item>, std::greater<item>>;
  

Это должно использовать operator> else использовать lampda в качестве компаратора.

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

Другая возможность заключается в использовании std::partial_sort первых 128 элементов, оставляя остальные несортированными, сверяйте с наивысшим значением в отсортированном массиве при вставке нового, чтобы увидеть, нужно ли его включать в лучшие оценки или просто помещать обратно в другие. Когда верхние оценки пусты, создайте новый std::partial_sort . Использование std::deque вместо std::vector может быть лучше в этом случае, из-за лучшего pop_front из O(1) . Необходимо выполнить некоторую дополнительную бухгалтерию.