🐛 Fix hash_bytes on big-endian and 32-bit targets - #148
Merged
Conversation
Signed-off-by: gkumbhat <Gaurav.Kumbhat@ibm.com>
Collaborator
|
if you need new crates published, please respond here. |
Contributor
Author
|
@aneubeck yes please. create release would be helpful Thank you for the quick review |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🐛 Fix
hash_byteson big-endian and 32-bit targetsThe problem
hash_byteshashes a token through the generic sliceHashimpl:That impl prefixes the element count via
Hasher::write_length_prefix→write_usize→write(&len.to_ne_bytes()).FnvHasherdoesn't override those,so the length reaches FNV in native byte order, at the host's pointer width.
The same token therefore hashes to a different value on a big-endian target or a 32-bit one.
That breaks the two things that assume the mapping is fixed:
hash_factorvalues callers hardcode — seebpe-openai/build.rs, whichpasses
17846336922010275747forcl100k_base,o200k_baseandvoyage3_base— were found byfind_hash_factor_for_dictionaryon a 64-bitlittle-endian machine. Once every hash changes, that factor no longer
guarantees collision freedom, and the
assert_eq!infrom_dictionaryfires. This breaks build on big-endian platforms.bytes_hash_to_tokenis a serialized field, so a dictionary serialized on onehost can't be deserialized correctly on a host of different endianness or
pointer width.
The fix
Write the length explicitly, at a fixed width and a fixed byte order:
The hash is now a property of the token bytes alone.
Compatibility
No change on 64-bit little-endian. The slice impl was already making exactly
these two
writecalls; the only difference isto_ne_bytes→to_le_bytesona value that is already 8 bytes wide. So existing hardcoded factors and already
serialized dictionaries stay valid.