У меня есть особая потребность, и наиболее важные проблемы:
- в памяти
- очень низкая занимаемая площадь памяти
- скорость
Вот моя "проблема": мне нужно хранить в памяти огромное количество очень разреженных бит-массивов. Эти биты устанавливаются только "добавляются" и должны использоваться в основном для пересечений. Огромным я имею в виду до 200 000 бит массивов.
Диапазон должен быть между [0... 16 000 000] для каждого битового набора.
Я провел предварительный тест с "только" 10 673 бит массивами, содержащими некоторые фактические данные, которые у меня есть, и получил следующие результаты:
1% of the bit arrays ( 106 bit arrays) Hamming weight: at most 1 bit set
5% of the bit arrays ( 534 bit arrays) Hamming weight: at most 4 bits set
10% of the bit arrays ( 1068 bit arrays) Hamming weight: at most 8 bits set
15% of the bit arrays ( 1603 bit arrays) Hamming weight: at most 12 bits set
20% of the bit arrays ( 2137 bit arrays) Hamming weight: at most 17 bits set
25% of the bit arrays ( 2671 bit arrays) Hamming weight: at most 22 bits set
30% of the bit arrays ( 3206 bit arrays) Hamming weight: at most 28 bits set
35% of the bit arrays ( 3740 bit arrays) Hamming weight: at most 35 bits set
40% of the bit arrays ( 4274 bit arrays) Hamming weight: at most 44 bits set
45% of the bit arrays ( 4809 bit arrays) Hamming weight: at most 55 bits set
50% of the bit arrays ( 5343 bit arrays) Hamming weight: at most 67 bits set
55% of the bit arrays ( 5877 bit arrays) Hamming weight: at most 83 bits set
60% of the bit arrays ( 6412 bit arrays) Hamming weight: at most 103 bits set
65% of the bit arrays ( 6946 bit arrays) Hamming weight: at most 128 bits set
70% of the bit arrays ( 7480 bit arrays) Hamming weight: at most 161 bits set
75% of the bit arrays ( 8015 bit arrays) Hamming weight: at most 206 bits set
80% of the bit arrays ( 8549 bit arrays) Hamming weight: at most 275 bits set
85% of the bit arrays ( 9083 bit arrays) Hamming weight: at most 395 bits set
90% of the bit arrays ( 9618 bit arrays) Hamming weight: at most 640 bits set
95% of the bit arrays (10152 bit arrays) Hamming weight: at most 1453 bits set
96% of the bit arrays (10259 bit arrays) Hamming weight: at most 1843 bits set
97% of the bit arrays (10366 bit arrays) Hamming weight: at most 2601 bits set
98% of the bit arrays (10473 bit arrays) Hamming weight: at most 3544 bits set
99% of the bit arrays (10580 bit arrays) Hamming weight: at most 4992 bits set
100% of the bit arrays (10687 bit arrays) Hamming weight: at most 53153 bits set
Увидев вовлеченные числа, я, очевидно, должен использовать сжатые бит-массивы, и это не проблема: он будет легко справляться с тем, что бит-массивы "добавляются только".
Битовые биты бит, которые включены, сгруппированы, но не полностью. Таким образом, вы будете иметь несколько бит в одной области (но обычно не один за другим, что делает RLE не очень хорошим для бит, который включен).
Мой вопрос: какое сжатие нужно использовать?
Теперь я не знаю, должен ли я использовать свой первый подход здесь или в ответе на мой собственный вопрос.
В основном я представил сценарий "наихудшего случая" с использованием очень тупой кодировки:
-
1 бит: если включено, следующие 5 бит определяют, сколько бит необходимо для вычисления "пропустить", если выключено, оптимизация: следующие 5 бит определяют, сколько бит слишком воспринимается буквально (это 'on' или "off", без пропусков) [это было бы переключено только тогда, когда определено, чтобы быть более эффективным, чем другое представление, поэтому, когда он срабатывает, он всегда должен быть оптимизацией (по размеру)]
-
5 бит: сколько бит мы можем пропустить до следующего бит на
-
x bits: skip
Вот пример: бит-бит имеет 3-битный набор, первый бит - 3 098 137, второй - 3 098 141, третий - 3 098 143.
+-- now we won't skip
|
| +-- 3 because we need 3 bits to store "6" (from 3 098 138 to 3 098 143)
| | +--- 3 098 141 is on
22 3 098 137 | 3 | +- 3 098 143 is on
1 10110 1011110100011000011001 0 00011 000101 etc.
Первый бит говорит о том, что мы будем пропускать биты. 5 следующих бит (всегда 5) сообщает, сколько бит нам нужно рассказать, сколько бит мы пропустим 22 бита, чтобы пропустить до 3 098 137 один бит, говорящий, что мы не пропускаем биты 5 следующих бит (всегда 5) сообщает, сколько бит мы будем читать "как есть", 6 бит: выключено, выключено, выключено, включено, выключено, по значению 3 098 141 и 3 098 143 включены и др.
Видимо, удивительная редкость этих бит-массивов, кажется, довольно размерна.
Итак, используя эту кодировку, я взял свои данные образца и вычислил сценарий "наихудшего случая" (я еще не написал algo, я бы предпочел, чтобы некоторые из них были здесь вначале): в основном я считал, что не только "оптимизация размера" никогда не будет срабатывать, а также, что 5 бит всегда будут установлены на их максимальное значение (24 бита), чего, конечно, не может быть.
Я сделал это просто, чтобы иметь очень грубое приближение того, что может быть "худшим из худших".
Я был очень приятно удивлен:
Worst case scenario:
108 913 290 bits needed for the 10 687 very sparse bit arrays
12.9 MB (13 295 KB)
Данные, являющиеся фактическими данными и всеми подобными данными, я знаю, что, если хуже будет хуже, я могу хранить 200 000 бит массивов примерно в 240 МБ, что хорошо.
Я уверен, что фактическая кодировка будет меньше, но, поскольку я еще не написал ее, я могу (очень легко) вычислить "худший случай", поэтому я только показываю, что один,
Любые подсказки/идеи относительно того, как сделать это более эффективным по размеру (помня, что это суперразребимые битовые массивы, что их должно быть сотни тысяч, что они должны быть в памяти и что они будут "добавлены" только ")?
О моем случае с добавлением только
В принципе, у меня есть одно растущее "пространство" (диапазон, но "простор" - это реальный термин, как я его понимаю) и множество бит-массивов, которые имеют несколько бит-множеств. Когда диапазон изменяется, скажем, от 0 до 1 000 000, все битовые массивы идут от 0 до 1 000 000. Когда диапазон растет до 1 000 001, тогда все бит-массивы растут тоже, на один бит. Но у большинства из этих бит-массивов будет добавлено "0", в то время как от 4 до 8 бит-массивов будет добавлено "1" в конце. Однако я не могу заранее предсказать, какая из бит-массивов будет содержать 0 или 1.
Итак, у меня есть множество бит-массивов, которые имеют одинаковый размер, все очень редкие (и 0,5% от их бит), и все они "растут" по мере роста диапазона (таким образом, все они всегда растут с одинаковой скоростью).
массивы Judyотлично. Но я читал о них несколько лет назад, и этот материал был "выше моей головы". Массивы Judy представляют собой C-only 20KLOC lib, и я определенно не переустанавливаю их. Но они потрясающие.
Итак, я думаю, мне нужно добавить, я бы хотел, чтобы все это оставалось относительно простым, что не так уж надуманно, увидев специальное свойство "добавить только" мои очень разреженные битовые массивы.