Я добавлю к ответу @ o11c , так как его формулировка может быть немного запутанной.Если мне нужно сжать последний бит и цикл процессора, я бы сделал следующее.
Мы начнем с построения сбалансированного бинарного дерева поиска, которое содержит 5% «что-то еще» случаев,Для каждого поиска вы быстро обходите дерево: у вас есть 10000000 элементов: 5% из которых находится в дереве: следовательно, структура данных дерева содержит 500000 элементов.Пройдя по времени O (log (n)), вы получите 19 итераций.Я не эксперт в этом, но я думаю, что есть некоторые реализации с эффективным использованием памяти.Давайте предположим:
- Сбалансированное дерево, чтобы можно было рассчитать позицию поддерева (индексы не нужно хранить в узлах дерева).Точно так же куча (структура данных) хранится в линейной памяти.
- 1 байтовое значение (от 2 до 255)
- 3 байта для индекса (10000000 занимает 23 бита, что соответствует 3 байта)
Итого, 4 байта: 500000 * 4 = 1953 кБ.Подходит для кеша!
Для всех остальных случаев (0 или 1) вы можете использовать битовый вектор.Обратите внимание, что вы не можете пропустить 5% других случаев для произвольного доступа: 1,19 МБ.
Комбинация этих двух использует приблизительно 3 099 МБ.Используя эту технику, вы сэкономите в 3,08 раза больше памяти.
Однако, это не превзойдет ответ @ Matteo Italia (который использует 2,76 МБ), а жаль.Есть ли что-нибудь, что мы можем сделать дополнительно?Наиболее ресурсоемкая часть - это 3 байта индекса в дереве.Если бы мы смогли уменьшить это значение до 2, мы бы сэкономили 488 КБ, а общее использование памяти составило бы: 2,622 МБ, что меньше!
Как нам это сделать?Мы должны уменьшить индексирование до 2 байтов.Опять же, 10000000 занимает 23 бита.Нам нужно уронить 7 бит.Мы можем просто сделать это, разделив диапазон 10000000 элементов на 2 ^ 7 (= 128) областей из 78125 элементов.Теперь мы можем построить сбалансированное дерево для каждого из этих регионов, в среднем с 3906 элементами.Выбор правильного дерева выполняется простым делением целевого индекса на 2 ^ 7 (или битовое смещение >> 7
).Теперь требуемый индекс для хранения может быть представлен оставшимися 16 битами.Обратите внимание, что есть некоторые издержки для длины дерева, которое необходимо сохранить, но это незначительно.Также обратите внимание, что этот механизм разбиения сокращает необходимое количество итераций для обхода дерева, теперь он сокращается на 7 итераций меньше, поскольку мы отбросили 7 бит: осталось только 12 итераций.
Обратите внимание, что теоретически можно повторитьпроцесс обрезки следующих 8 битов, но для этого потребуется создать 2 ^ 15 сбалансированных деревьев, в среднем ~ 305 элементов.В результате получится 2,143 МБ, всего 4 итерации для обхода дерева, что является значительным ускорением по сравнению с 19 итерациями, с которых мы начали.
В заключение: это лучше, чем 2-битная векторная стратегиянемного использования памяти, но это целая борьба для реализации.Но если это может сделать разницу между подгонкой кеша или нет, возможно, стоит попробовать.