Эффективное отображение от 2 ^ 24 значений до 2 ^ 7 индекса - PullRequest
1 голос
/ 05 декабря 2010

У меня есть структура данных, которая хранит среди прочего 24-битное значение.У меня есть много этих объектов.

Чтобы минимизировать стоимость хранения, я вычислил 2 ^ 7 наиболее важных значений из 2 ^ 24 возможных значений и сохранил их в статическом массиве.Таким образом, мне нужно только сохранить 7-битный индекс в этом массиве в моей структуре данных.

Проблема в том, что я получаю эти 24-битные значения и мне нужно преобразовать их в мой 7-битный индекс налетать (предварительная обработка невозможна).Вычисление в основном представляет собой поиск, который из 2 ^ 7 значений подходит лучше всего.Очевидно, это занимает некоторое время для большого числа объектов.

Очевидным решением будет создание простого отображающего массива байтов длиной 2 ^ 24.Но это займет 16 МБ ОЗУ.Слишком много.

Одно наблюдение массива 16 МБ: в среднем 31 последовательное значение совпадает.К сожалению, есть также ряд последовательных значений, которые отличаются.


Как бы вы реализовали это преобразование из 24-разрядного значения в 7-разрядный индекс, сэкономив как можно больше ЦП и памяти?

Ответы [ 6 ]

1 голос
/ 05 декабря 2010

Как идея ... Увеличьте индексную таблицу до 8 битов, затем зафиксируйте в ней все 3 байта 24-битного слова. тогда ваша таблица будет состоять из этого 8-битного хеш-значения и индекса обратно к исходному 24-битному значению.

Поскольку ваши данные похожи на RGB, может потребоваться более сложный метод хеширования.


 bit24var        & 0x000f gives you the right hand most char.
(bit24var >> 8)  & 0x000f gives you the one beside it.
(bit24var >> 16) & 0x000f gives you the one beside that.

Да, вы думаете правильно. Вполне вероятно, что одно или несколько из 24-битных значений будут хэшироваться к одному и тому же индексу из-за принципа голубиного отверстия .

Один из способов разрешения хеш-коллизии - это использование какой-то цепочки.

1 голос
/ 05 декабря 2010

Трудно сказать, не зная, что такое определение "лучше всего подходит". Возможно, kd-tree позволит выполнить подходящий поиск, основанный на близости по некоторой метрике или другому, так что вы быстро исключите большинство кандидатов, и вам нужно будет только проверить некоторые из 2 ^ 7, чтобы увидеть самый лучший?

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

0 голосов
/ 05 декабря 2010

Другая идея состоит в том, чтобы представить массив 24BitValue в битовой карте. Хороший беззнаковый символ может содержать 8 битов, поэтому потребуется 2 ^ 16 элементов массива. Это 65536. Если установлен соответствующий бит, то вы знаете, что это конкретное значение 24BitValue присутствует в массиве и требует проверки.

Нужен итератор, чтобы пройти через массив и найти следующий установленный бит. Некоторые машины фактически предоставляют операцию «найти первый бит» в своем наборе команд.

Удачи в ваших поисках. Дайте нам знать, как все получается.

Evil.

0 голосов
/ 05 декабря 2010

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

0 голосов
/ 05 декабря 2010

Поскольку вы уже знаете, какое из 2 ^ 24 значений вам нужно сохранить (т. Е. 2 ​​^ 7 значений, которые вы определили как важные), мы можем просто отфильтровать входящие данные и присвоить значение, начиная с 0 и выше2 ^ 7-1, к этим значениям, как мы с ними сталкиваемся.Конечно, нам понадобится какой-то способ отследить, какое из важных значений мы уже видели и уже присвоили метку в [0,2 ^ 7).Для этого мы можем использовать некоторую реализацию словаря на основе дерева или хеш-таблицы (например, std::map в C ++, HashMap или TreeMap в Java или dict в Python).

Код может выглядетьчто-то вроде этого (я использую гораздо меньший диапазон значений):

import random

def make_mapping(data, important):
    mapping=dict() # dictionary to hold the final mapping
    next_index=0 # the next free label that can be assigned to an incoming value
    for elem in data:
        if elem in important: #check that the element is important
            if elem not in mapping: # check that this element hasn't been assigned a label yet
                mapping[elem]=next_index
                next_index+=1 # this label is assigned, the next new important value will get the next label 
    return mapping

if __name__=='__main__':
    important_values=[1,5,200000,6,24,33]
    data=range(0,300000)
    random.shuffle(data)
    answer=make_mapping(data,important_values)
    print answer

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

0 голосов
/ 05 декабря 2010

Сколько у вас 2 ^ 24? Можете ли вы отсортировать эти значения и сосчитать их путем подсчета количества последовательных значений.

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