У меня особая потребность, и самые важные проблемы:
- в памяти
- очень низкий объем памяти
- скорость
Вот моя «проблема»: мне нужно хранить в памяти огромное количество очень редких битовых массивов.Эти наборы битов «только для добавления» и должны использоваться в основном для пересечений.Под огромным я подразумеваю до 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 битов определяют, сколько битов тоже нужно брать буквально (то есть «включено» или «выключено», без пропуска) [это будет переключено только на значение, определенное как большееэффективнее, чем другое представление, поэтому, когда оно включается, оно всегда должно быть оптимизацией (по размеру)]
5 битов: сколько бит мы можем пропустить до следующего бита на
x бит: пропустить
Вот пример: битовый массив имеет 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 включены и т. д.
Видите удивительную разреженность этих битмассивы, это кажется довольно экономичным по размеру.
Таким образом, используя эту кодировку, я взял свои примерные данные и вычислил сценарий «наихудшего случая» (я еще не написал алгоритм, я предпочел бы сначала получить несколько исходных данных): в основном я рассмотрелчто не только «оптимизация размера» никогда не включится, а также, что 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% их битов установлены), и все они "растут" по мере увеличения диапазона (поэтому они все всегда растут с одинаковой скоростью). </p>
массивы Джуди отличный.Но я читал о них несколько лет назад, и все это было «над моей головой».Массивы Judy - это библиотека C-only 20KLOC, и я определенно не буду реализовывать это заново.Но они удивительны.
Так что, думаю, мне нужно добавить, что я бы хотел, чтобы все это оставалось относительно простым, а это не так уж надуманно, как особенное свойство "добавить только" моего очень разреженного битамассивы.