LINUX.ORG.RU

Как получить уже вычисленный hash в std::unordered_map?

 


0

3

Приветствую.

Не понимаю из документации так можно зачем то

std::unordered_map<std::string, Т> umap;
umap["блабла"] = blabla;

auto hash_fn = umap.hash_function();
size_t hash_value = hash_fn("блабла");

Но вот если ключ длинный - как избежать повторного вычисления? Хотелось бы дополнительно использовать это значение.

ЗЫ. C++11/14

★★★

Последнее исправление: wolverin (всего исправлений: 1)

используй в мапе не строку, а объект вида

struct my_key { std::wstring key; int hash; }

hash вычисляй при создании my_key. В мапу передавай свои std::hash<my_key> и std::equal_to<my_key>.

MirandaUser2
()
Последнее исправление: MirandaUser2 (всего исправлений: 1)

Но вот если ключ длинный - как избежать повторного вычисления? Хотелось бы дополнительно использовать это значение.

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

если функция почему-то излишне сложная, можно свою простую сделать.

alysnix ★★★
()
Ответ на: комментарий от alysnix

да мне не хранить, просто уже вычислено и место занимает - хочу использовать это уникальное значение от строки, единственно стандартный std::hash в зависимости от архитектуры разный результат дает )

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

вообще если скорость особо критична, лучше использовать свои коллекции и свои хеши. опять же можно подобрать простые хеши для своих данных, что будет работать не хуже сложных.

а для простых хешей, проще вообще его вычислять на лету.

стандартный хеш как пишут есть MurmurHashUnaligned2. он довольно сложный на самом деле.

короче от задачи зависит, и от данных, по которым считать надо хеш.

alysnix ★★★
()
Ответ на: комментарий от alysnix

MurmurHashUnaligned2

это же std::hash<std::string>, а он почему то на x86_64 один, а на ARM (32bit) другой (естественно size_t на них разный)

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)
Ответ на: комментарий от wolverin

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

И в cpp похоже тоже: https://en.cppreference.com/w/cpp/utility/hash

Hash functions are only required to produce the same result for the same input within a single execution of a program; this allows salted hashes that prevent collision denial-of-service attacks.

А тебе нужен т.н. stable hash.

MirandaUser2
()
Ответ на: комментарий от wolverin

в зависимости от архитектуры разный результат дает

Хеши отличаются тк в разных системах может отличаться порядок следования битов (big/little-endian) и разрядность 32/64, тот же md5 использует little-endian values.

Т.е. если endianness отличается, то указываете в ARM системе set endian little или используете rev intrinsic (или boost/endian/conversion.hpp и тд) для преобразования big в little. После чего хеши совпадают если совпадает разрядность.

Если разрядность не совпадает, например ARM 32 битная, а ваша система - 64 битная, то открываете md5.c, ищите

typedef unsigned long int UINT4;

и меняете на

typedef uint32_t UINT4;

после чего md5 хеши будут одинаковые.

Obezyan
()
Ответ на: комментарий от wolverin

а потом в другом месте что то не съедет!?

Обязательно съедет, это же С++. А если серьезно, то проверяя (и конвертируя) только нужные значения в little endian и используя измененный хеш алгоритм только в этом случае все остальное останется на месте.

Obezyan
()

Если тебе нужен перформанс, то возьми что-то получше std::unordered_map, например absl::flat_hash_map или tsl::robin_map.

А если ключ строка, как в твоём случае, то tsl::array_hash порвёт всех как тузик грелку. И там есть precalculated_hash в API.

snizovtsev ★★★★★
()
Последнее исправление: snizovtsev (всего исправлений: 4)
Ответ на: комментарий от Lrrr

хеш таблица не особо нужна, так наверное 2-3 записи в ней обычно будет, ну предельно до 100 оцениваю не имея статистики, просто от строки все равно считать нужно какой то хеш для url в имя topic для mqtt и почему бы этот хеш не использовать повторно ничего не считая.

wolverin ★★★
() автор топика

не знаю рабочее ли это, но компилируется )

#include <zlib.h>

struct stArchive_t {
    const string topic;
    size_t hash;
    atomic_short status;
    atomic<float> speed;

    stArchive_t(const string & _topic)
    :   topic(...),
        hash(crc32(0L, (const unsigned char*)topic.c_str(), topic.length())),
        status(...),
        speed(...)
    {}

    bool operator==(const stArchive_t & k) const
    {
        return hash == k.hash;
    }
};

struct hashArchive_t {
    size_t operator()(const stArchive_t & k) const
    {
        return k.hash;
    }
};

std::unordered_map<stArchive_t, stArchive_t *, hashArchive_t> urls;

wolverin ★★★
() автор топика
Ответ на: комментарий от wolverin

вопщим так и поступил - урл всегда уникален сам по себе, все что не буквы-цифры коверчу в хекс - вот и нормальный достаточно уникальный хеш, а хеш контейнера оставил в покое, тем более что там специально реализован рехеш таблицы.

wolverin ★★★
() автор топика