Поиск членства в массиве диапазонов - PullRequest
0 голосов
/ 12 февраля 2010

Как часть нашей системной симуляции, я моделирую пространство памяти с 64-битной адресацией, используя разреженный массив памяти и веду список объектов для отслеживания буферов, выделенных в пространстве памяти. Буферы распределяются и удаляются динамически.

У меня есть функция, которая ищет заданный адрес или диапазон адресов в выделенных буферах, чтобы увидеть, есть ли доступ к модели памяти в выделенном пространстве, или нет, и мой первый разрез "просматривает все буферы, пока не найдет совпадение "замедляет наше моделирование на 10%. Наше проверяемое оборудование осуществляет много обращений к памяти, которые должны проверяться симуляцией.

Итак, я пытаюсь оптимизировать. Объекты буфера памяти содержат начальный адрес и длину. Я думаю о сортировке массива объектов по начальному адресу при создании объекта, а затем, когда вызывается функция проверки, выполняет бинарный поиск по массиву, чтобы определить, попадает ли данный адрес в начальный / конечный диапазон.

Есть ли лучшие / более быстрые способы сделать это? Должен быть какой-то более быстрый / более крутой алгоритм, использующий кучи или хэш-сигнатуры или что-то в этом роде, верно?

Ответы [ 3 ]

2 голосов
/ 12 февраля 2010

Двоичный поиск в отсортированном массиве работает, но замедляет выделение / освобождение.

Простой случай - сделать упорядоченное двоичное дерево (красно-черное дерево, дерево AVR и т. Д.), Проиндексированное по начальному адресу, чтобы вставка (выделение), удаление (освобождение) и поиск были все O (log n ). Большинство современных языков уже предоставляют такую ​​структуру данных (например, C ++ std::map).

0 голосов
/ 13 февраля 2010

В основном ваша проблема заключается в том, что у вас есть определенные интервалы «действительной» памяти, память вне этих интервалов «недействительна», и вы хотите проверить заданный адрес, находится ли он в допустимом блоке памяти или нет.

Вы определенно можете сделать это, сохраняя начальные адреса всех выделенных блоков в двоичном дереве; затем найдите самый большой адрес в запрашиваемом адресе или ниже и просто убедитесь, что адрес соответствует длине действительного адреса. Это дает вам O (log n) времени запроса, где n = количество выделенных блоков. Конечно, этот же запрос можно использовать и для поиска самого блока, так что вы также можете прочитать содержимое блока по заданному адресу, который, я думаю, вам также понадобится.

Однако это не самая эффективная схема. Вместо этого вы можете использовать дополнительно одномерные деревья пространственных подразделений, чтобы пометить недействительные области памяти. Например, используйте дерево с коэффициентом ветвления 256 (соответствует 8 битам), которое отображает все эти блоки 16 КБ, в которых есть только недействительные адреса, на «1», а другие на «0»; дерево будет иметь только два уровня и будет очень эффективным для запроса. Когда вы видите адрес, сначала спросите это дерево, если оно определенно недействительно; только когда это не так, запросить другой. Это ускорит процесс ТОЛЬКО ЕСЛИ ВЫ ПОЛУЧИТЕ МНОГО НЕВЕРНЫХ ССЫЛК НА ПАМЯТЬ; если все ссылки на память действительно действительны и вы просто утверждаете, вы ничего не сохраните. Но вы можете перевернуть эту идею и использовать метку дерева для всех тех блоков 16 КБ или 256 В, которые имеют только допустимые адреса внутри них; насколько велико дерево, зависит от того, как работает ваш имитатор распределения памяти.

0 голосов
/ 12 февраля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...