Фон
Я использую небольшую статическую хеш-таблицу (линейное зондирование), которая мне нужна на этапе в конвейере рендеринга OpenGL, где я должен извлекать и обновлять ключи типа int64_t и некоторые данные как можно быстрее. Короче говоря, на этом этапе речь идет о преобразовании больших идентификаторов в небольшие локальные индексы, которые используются на последующих этапах (поэтому здесь, на этом этапе, мне действительно нужно иметь дело с 64-битными ключами один раз, и я не могу использовать 32-битные ключи).
Я долго экспериментировал, чтобы найти хеш-функцию, которая бы работала как на 32-битной, так и на 64-битной архитектуре (iOS и Android-смартфоны). Естественно, на 32-битных устройствах хеширование 64-битных ключей намного медленнее, чем хеширование 32-битных ключей (в моем тестовом случае почти 10 раз).
Теперь я очень уверен в хэше, который я нашел здесь на SO, который превосходит 32-битный финализатор MurmurHash3 в моем случае (с некоторыми коллизиями, но не имеет значения в моем случае):
https://stackoverflow.com/a/12996028/1708349
На данный момент все работает хорошо, но вот подвох: я наивно присваиваю 64-битный ключ типу int32_t, прежде чем его хешировать — это сделано по соображениям производительности для 32-битных платформ. Кажется, это работает, большие данные обернуты вокруг. Но загвоздка в том, что это поведение не определено.
Итак, мой вопрос: как лучше (например, определенное поведение компилятора) назначить тип int64_t для типа int32_t, поэтому он оборачивается — и, например, не просто назначается младший 32-битный из 64-битного типа int?
Это моя настоящая хеш-функция:
inline int32_t hash2(int64_t k) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"int32_t x = k;
#pragma clang diagnostic pop
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x) * 0x45d9f3b;
x = ((x >> 16) ^ x);
return x;
}
Задача ещё не решена.