From 64f2a10fbba5b64a4d3eb72599ae70829a095150 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Thu, 2 Nov 2023 12:55:13 -0400 Subject: [PATCH] Return hash_resize{} from hash_alloc{} --- src/singeli/src/hashmap.singeli | 42 ++++++++++++++++-------------- src/singeli/src/search.singeli | 13 ++++----- src/singeli/src/selfsearch.singeli | 29 +++++++++++---------- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/singeli/src/hashmap.singeli b/src/singeli/src/hashmap.singeli index 1301fb51..0e7ca77a 100644 --- a/src/singeli/src/hashmap.singeli +++ b/src/singeli/src/hashmap.singeli @@ -28,9 +28,13 @@ def hash_val{x:u32 & hasarch{'SSE4.2'}} = { # Allocate and initialize resizing hash table # Initial size sz+ext and maximum size msz+ext # One region for each type in Ts initialized with value from v0s -def hash_alloc{sz, msz, ext, Ts, v0s} = { +def hash_alloc{logsz, msz, ext, Ts, v0s} = { def ws = each{width,Ts} each{assert, slice{ws,0,-1} >= slice{ws,1}} # Doesn't do alignment + # Variables updated on resize + sz := usz~~1 << logsz + sh := tupsel{0,ws} - logsz + def add{}=0; def add{a,...r} = a+add{...r} halloc := talloc{u8, (msz+ext)*add{...ws/8}} szo := msz-sz # Beginning of allocation to initial table @@ -40,25 +44,25 @@ def hash_alloc{sz, msz, ext, Ts, v0s} = { def pl{{...R, T}} = { def ps=pl{R}; tup{...ps, *T~~pe{ps}+szo} } ptrs := pl{Ts} each{memset{., ., sze}, ptrs, v0s} - tup{ptrs, {}=>tfree{halloc}} -} -def hash_resize{hash,vals, x0,sh,sz,ext,cc, m} = { - dif := sz*((1< { val -= dif; memset{val, 0, dif} }, vals} - @for (j from dif to sz + ext) { - h := hash->j - if (h != x0) { - hash <-{j} x0 - k0 := h>>sh; k := k0; while (hash->k!=x0) ++k - cc += cast_i{usz, k-k0} - hash <-{k} h - each{{val} => { v := val->j; val <-{j} 0; val <-{k} v }, vals} + def hash_resize{cc, m} = { + dif := sz*((1< { p -= dif; memset{p, v, dif} }, ptrs, v0s} + def {hash, ...vals} = ptrs; def {h0, ...v0r} = v0s + @for (j from dif to sz + ext) { + h := hash->j + if (h != h0) { + hash <-{j} h0 + k0 := h>>sh; k := k0; while (hash->k!=h0) ++k + cc += cast_i{usz, k-k0} + hash <-{k} h + each{{p,v0} => { v := p->j; p <-{j} v0; p <-{k} v }, vals, v0r} + } } } + + tup{ptrs, sz, sh, hash_resize, {}=>tfree{halloc}} } diff --git a/src/singeli/src/search.singeli b/src/singeli/src/search.singeli index b238fbf9..36c9ff85 100644 --- a/src/singeli/src/search.singeli +++ b/src/singeli/src/search.singeli @@ -347,10 +347,11 @@ fn hashtab{T, name}(rp:*rty{name}, ip:*T, m:usz, fp:*T, n:usz) = { def stop = m log := clzc{m} + # Max size msl := clzc{m} + 2 - sh := wt - tern{msl<14, msl, 12+(msl&1)} # Shift to fit to table - sz := usz~~1 << (wt - sh) # Initial size - msz := usz~~1 << msl # Max sz + msz := usz~~1 << msl + # Starting log-size + sl := msl; if (msl>=14) sl = 12+(msl&1) b:usz = 64 # Block size # Filling e slots past the end requires e*(e+1)/2 collisions, so @@ -358,8 +359,8 @@ fn hashtab{T, name}(rp:*rty{name}, ip:*T, m:usz, fp:*T, n:usz) = { ext := tern{m<=b, m, b + (usz~~1 << (log/2 + 1))} maxh := T~~maxvalue{T} def aux = prim!='∊' - def {tabs, hash_free} = hash_alloc{ - sz, msz, ext, tup{T, ...aux**u32}, tup{maxh, ...aux**0} + def {tabs, sz, sh, hash_resize, hash_free} = hash_alloc{ + sl, msz, ext, tup{T, ...aux**u32}, tup{maxh, ...aux**0} } def {hash,...vals} = tabs @@ -396,7 +397,7 @@ fn hashtab{T, name}(rp:*rty{name}, ip:*T, m:usz, fp:*T, n:usz) = { # Check collision counter and possibly resize (needs tuning) if (cc >= stop and sz == msz) goto{abort} if (16*cc >= stop and sz < msz) { - hash_resize{hash,vals, maxh,sh,sz,ext,cc, 2} # Resize hash, factor of 4 + hash_resize{cc, 2} # Factor of 4 if (cc >= stop) goto{abort} } } diff --git a/src/singeli/src/selfsearch.singeli b/src/singeli/src/selfsearch.singeli index 5600825c..37571407 100644 --- a/src/singeli/src/selfsearch.singeli +++ b/src/singeli/src/selfsearch.singeli @@ -16,12 +16,23 @@ fn selfhashtab{T, name}(rp:*rty{name}, xp:*T, n:usz) = { def {res0,stop} = if (prim=='∊') tup{1,n>>has_radix} else tup{0,2*n} log := clzc{n} + # Max size msl := clzc{n+n/2} + 1; if (has_radix and msl>20) msl=20 - sh := wt - tern{msl<14, msl, 12+(msl&1)} # Shift to fit to table - sz := usz~~1 << (wt - sh) # Initial size - msz := usz~~1 << msl # Max sz + msz := usz~~1 << msl + # Starting log-size + sl := msl; if (msl>=14) sl = 12+(msl&1) b:usz = 64 # Block size + # Filling e slots past the end requires e*(e+1)/2 collisions, so + # n entries with <2 each can fill 0} + rp <-{0} res0 + def aux = prim!='∊' + def {{hash,...vals}, sz, sh, hash_resize, hash_free} = hash_alloc{ + sl, msz, ext, tup{T, ...aux**u32}, tup{x0, ...aux**0} + } + # Resize or abort if more than 1/2^thresh collisions/element def {set_thresh, div_thresh} = { t:usz = 0 # Shift amount @@ -40,16 +51,6 @@ fn selfhashtab{T, name}(rp:*rty{name}, xp:*T, n:usz) = { } set_thresh{} - # Filling e slots past the end requires e*(e+1)/2 collisions, so - # n entries with <2 each can fill 0} - rp <-{0} res0 - def aux = prim!='∊' - def {{hash,...vals}, hash_free} = hash_alloc{ - sz, msz, ext, tup{T, ...aux**u32}, tup{x0, ...aux**0} - } - def {output, write_res} = match (prim) { {('∊')} => tup{{b}=>b, {j,h,k,x0} => { hash<-{j}h; k!=h }} {('⊒')} => { @@ -91,7 +92,7 @@ fn selfhashtab{T, name}(rp:*rty{name}, xp:*T, n:usz) = { if (has_radix and i < n/2 and sz >= 1<<18) goto{break} # Avoid resizing if close to the end if (cc>=stop or p64{n-i}*dc >= (p64{i}*p64{n+i})>>(5+log-(wt-sh))) { - hash_resize{hash,vals, x0,sh,sz,ext,cc, 2} # Resize hash, factor of 4 + hash_resize{cc, 2} # Factor of 4 if (cc >= stop) goto{break} set_thresh{} }