Корректная структура данных для использования для (это конкретное) истекающий кэш?

Я должен читать из набора данных, который является очень большим, высоко связанный, данные справедливо локализуются, и чтения являются довольно дорогими. Конкретно:

  1. Наборы данных 2gigs - 30gigs в размере, таким образом, я должен отобразить разделы файла в память для чтения. Это очень дорого по сравнению с остальной частью работы, которую я делаю в алгоритме. От профилирования я нашел, что примерно 60% времени потрачены, читая память, таким образом, это - правильное место, чтобы начать оптимизировать.
  2. При работе на часть этого набора данных я должен следовать, ссылки в нем (вообразите это как то, чтобы быть подобным связанному списку), и в то время как тем чтениям не гарантируют в какой-либо степени последовательному, они справедливо локализуются. Это означает:
  3. Скажем, например, мы воздействуем на 2 megs памяти за один раз. При чтении 2 megs данных в память примерно 40% чтений, которые я должен буду впоследствии сделать, будут в тех же самых 2 megs памяти. Примерно 20% чтений будут чисто произвольным доступом в остальной части данных, и другие 40% очень вероятно связываются назад в 2meg сегмент, который указал на этого.

От знания проблемы и от профилирования, я полагаю, что представление кэша к программе поможет значительно. То, что я хочу сделать, создают кэш, который содержит блоки N X megs памяти (N и X настраивающийся, таким образом, я могу настроить ее), который я могу проверить сначала, прежде, чем иметь необходимость отобразить другой раздел памяти. Кроме того, чем дольше что-то было в кэше, тем менее вероятно случается так, что мы запросим, что память в ближайшей перспективе, и таким образом, самые старые данные должны будут истечь.

В конце концов, это, мой вопрос очень прост: Какая структура данных была бы лучшей для реализации кэша этой природы?

У меня должны быть очень быстрые поиски, чтобы видеть, находится ли данный адрес в кэше. С каждой "мисс" кэша я захочу истечь самый старый член его и добавить нового участника. Однако я планирую попытаться настроить его (путем изменения суммы, это кэшируется), таким образом, что 70% или больше чтений являются хитами.

Мои существующие взгляды состоят в том, чтобы использовать любого дерево AVL (LOG2 n для ищут/вставляют/удаляют), было бы самым безопасным (никакие вырожденные случаи). Моя другая опция является редкой хеш-таблицей, таким образом, что поиски были бы O (1) в лучшем случае. В теории это могло ухудшиться в O (n), но на практике я мог поддержать коллизии на низком уровне. Беспокойство здесь было бы то, сколько времени оно берет, чтобы найти и удалить самую старую запись в хеш-таблице.

У кого-либо есть какие-либо мысли или предложения на том, какая структура данных была бы лучшей здесь, и почему?

5
задан LCC 20 June 2010 в 21:45
поделиться

3 ответа

3
ответ дан 14 December 2019 в 08:42
поделиться

Поместите кеш в два отсортированных дерева (подойдет AVL или любая другая разумно сбалансированная реализация дерева - лучше использовать один из библиотеки, чем создавать свой собственный).

Одно дерево должно быть отсортировано по позиции в файле. Это позволяет вам выполнять поиск в журнале (n), чтобы узнать, есть ли там ваш кеш.

Другое дерево должно сортироваться по времени использования (которое может быть представлено числом, которое увеличивается на единицу при каждом использовании). Когда вы используете кешированный блок, вы удаляете его, обновляете время и снова вставляете. Это также займет log (n). Если вы промахнетесь, удалите самый маленький элемент дерева и добавьте новый блок как самый большой. (Не забудьте также удалить / добавить этот блок в дерево по позициям в файле.)

Если в вашем кэше не так много элементов, вам все равно будет лучше, если просто сохранить все в отсортированном массиве (с использованием сортировки вставкой для добавления новых элементов). Перемещение 16 элементов вниз на одну позицию в массиве происходит невероятно быстро.

2
ответ дан 14 December 2019 в 08:42
поделиться

Если 60% вашего алгоритма - это ввод-вывод, я предполагаю, что фактический дизайн кеша на самом деле не имеет большого значения - любой вид кеша может быть существенным ускорением.

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

Хэш-карты предоставляются под разными именами (чаще всего, неупорядоченная карта) во многих реализациях. У Boost есть один, он есть в TR1 и т. Д. Большим преимуществом hash_map является меньшая потеря производительности при увеличении числа и большая гибкость в отношении значений ключей.

2
ответ дан 14 December 2019 в 08:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: