wyhash microoptimization
This commit is contained in:
parent
98e3021efb
commit
fd1ac7487c
@ -29,6 +29,7 @@ NOINLINE u64 bqn_hashArr(B x, const u64 secret[4]) { // TODO manual separation o
|
||||
bytes = xia*sizeof(B);
|
||||
break;
|
||||
}
|
||||
assert(bytes!=0);
|
||||
u64 r = wyhash(data, bytes, shHash, secret);
|
||||
if (isTemp) TFREE(data);
|
||||
dec(x);
|
||||
|
||||
@ -113,28 +113,39 @@ static inline uint64_t _wyr4(const uint8_t *p) {
|
||||
return (((v >> 24) & 0xff)| ((v >> 8) & 0xff00)| ((v << 8) & 0xff0000)| ((v << 24) & 0xff000000));
|
||||
}
|
||||
#endif
|
||||
static inline uint64_t _wyr3(const uint8_t *p, size_t k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];}
|
||||
//wyhash main function
|
||||
|
||||
#ifdef __BMI2__
|
||||
#include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
//wyhash main function; assumes len>0 and that it can read past the end of the input
|
||||
FORCE_INLINE uint64_t wyhash(const void *key, size_t len, uint64_t seed, const uint64_t *secret){
|
||||
const uint8_t *p=(const uint8_t *)key; seed^=*secret; uint64_t a, b;
|
||||
if(_likely_(len<=16)){
|
||||
if(_likely_(len>=4)){ a=(_wyr4(p)<<32)|_wyr4(p+((len>>3)<<2)); b=(_wyr4(p+len-4)<<32)|_wyr4(p+len-4-((len>>3)<<2)); }
|
||||
else if(_likely_(len>0)){ a=_wyr3(p,len); b=0;}
|
||||
else a=b=0;
|
||||
}
|
||||
else{
|
||||
const uint8_t *p = (const uint8_t *)key; seed^=*secret; uint64_t a, b;
|
||||
if (_likely_(len<=16)) {
|
||||
#ifdef __BMI2__
|
||||
if (len>8) { a = _wyr8(p); b = _bzhi_u64(_wyr8(p+8), (len-8)*8); }
|
||||
else { a = 0; b = _bzhi_u64(_wyr8(p ), len *8); }
|
||||
#else
|
||||
if (len==16) { a = _wyr8(p); b = _wyr8(p+8); }
|
||||
else {
|
||||
if (len>=8) { a = _wyr8(p); p+= 8; }
|
||||
else a = 0;
|
||||
b = _wyr8(p) & (((uint64_t)1)<<((8*len)&63))-1;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
size_t i=len;
|
||||
if(_unlikely_(i>48)){
|
||||
if (_unlikely_(i>48)){
|
||||
uint64_t see1=seed, see2=seed;
|
||||
do{
|
||||
do {
|
||||
seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed);
|
||||
see1=_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^see1);
|
||||
see2=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see2);
|
||||
p+=48; i-=48;
|
||||
}while(_likely_(i>48));
|
||||
} while (_likely_(i>48));
|
||||
seed^=see1^see2;
|
||||
}
|
||||
while(_unlikely_(i>16)){ seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); i-=16; p+=16; }
|
||||
while (_unlikely_(i>16)) { seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed); i-=16; p+=16; }
|
||||
a=_wyr8(p+i-16); b=_wyr8(p+i-8);
|
||||
}
|
||||
return _wymix(secret[1]^len,_wymix(a^secret[1],b^seed));
|
||||
|
||||
@ -10,9 +10,10 @@ test/moreCfgs.sh path/to/mlochbaum/BQN // run "2+2" in a bunch of configurations
|
||||
./BQN test/equal.bqn // fuzz-test 𝕨≡𝕩
|
||||
./BQN test/copy.bqn // fuzz-test creating new arrays with elements copied from another
|
||||
./BQN test/bitcpy.bqn // fuzz-test bit_cpy; requires a CBQN build with -DTEST_BITCPY
|
||||
./BQN test/hash.bqn // fuzz-test hashing
|
||||
./BQN test/squeezeValid.bqn // fuzz-test squeezing giving a correct result; requires a CBQN build with -DEEQUAL_NEGZERO
|
||||
./BQN test/squeezeExact.bqn // fuzz-test squeezing giving the exact smallest result; requires a CBQN build with -DEEQUAL_NEGZERO
|
||||
./BQN test/random.bqn // various random tests
|
||||
./BQN test/random.bqn // tests for various small things
|
||||
make -C test/ffi // test FFI functionality; expects both regular and shared library CBQN builds to already exist
|
||||
|
||||
legacy utilities:
|
||||
|
||||
25
test/hash.bqn
Normal file
25
test/hash.bqn
Normal file
@ -0,0 +1,25 @@
|
||||
# note: tests only bit/i8/i16/i32 arrays; no f64/c8/c16/c32/generic array tests
|
||||
u ← ⌊100×(•UnixTime+1|100וMonoTime)@
|
||||
R ← (•MakeRand •Show u).Range
|
||||
|
||||
M ← (2⋆32)⊸×⊸+´
|
||||
Test ← { 𝕊:
|
||||
width ← 1‿8‿16‿32⊑˜R 4
|
||||
count ← 1+R (width=1)⊑32‿256
|
||||
data ← (width×count) R 2
|
||||
n ← 1+R count
|
||||
cast ← {width=1? ⊢; ⟨1⋄width‿'i'⟩ •bit._cast}
|
||||
iota ← ↕≠data
|
||||
shifts ← ↕1+count-n
|
||||
exp ← >(-shifts)(width/⌽)¨<n>↕count
|
||||
got ← >1↓¨∊¨<˘⍉>{
|
||||
a ← Cast data≠𝕩≠iota
|
||||
shifts (M∘•Hash n↑↓)¨ <a
|
||||
}¨¯1∾iota
|
||||
+´∘⥊¨ exp(>⋈<)got
|
||||
}
|
||||
|
||||
fails ← 0‿0
|
||||
{𝕊: fails+↩ Test@}¨↕1000
|
||||
•Out ∾⟨"Collisions: " ⋄ •Repr 0⊑fails ⋄ " (expected 0, assuming no actual hash collisions)"⟩
|
||||
•Out ∾⟨"Mismatches: " ⋄ •Repr 1⊑fails ⋄ " (expected 0)"⟩
|
||||
Loading…
Reference in New Issue
Block a user