AVX2 1-byte Deduplicate implementation
This commit is contained in:
parent
9658104f3e
commit
1700d84740
@ -214,6 +214,7 @@ static NOINLINE void memset64(u64* p, u64 v, usz l) { for (usz i=0; i<l; i++) p[
|
||||
/*AUXMOVE*/u32 v = val[j]; val[j] = 0; val[k] = v;)
|
||||
|
||||
extern void (*const avx2_mark_firsts_u8)(void*,uint64_t,void*,void*);
|
||||
extern u64 (*const avx2_deduplicate_u8)(void*,uint64_t,void*,void*);
|
||||
|
||||
B memberOf_c1(B t, B x) {
|
||||
if (isAtm(x) || RNK(x)==0) thrM("∊: Argument cannot have rank 0");
|
||||
@ -545,7 +546,8 @@ B find_c1(B t, B x) {
|
||||
if (isAtm(x) || RNK(x)==0) thrM("⍷: Argument cannot have rank 0");
|
||||
usz n = *SH(x);
|
||||
if (n<=1) return x;
|
||||
if (TI(x,elType)==el_bit && RNK(x)==1) {
|
||||
u8 xe = TI(x,elType);
|
||||
if (xe==el_bit && RNK(x)==1) {
|
||||
u64* xp = bitarr_ptr(x);
|
||||
u64 x0 = 1 & *xp;
|
||||
usz i = bit_find(xp, n, !x0); decG(x);
|
||||
@ -553,5 +555,15 @@ B find_c1(B t, B x) {
|
||||
rp[0] = 2 ^ -x0;
|
||||
return r;
|
||||
}
|
||||
#if SINGELI_AVX2
|
||||
if (elWidth(xe)==1 && RNK(x)==1 && !FL_HAS(x, fl_asc|fl_dsc)) {
|
||||
TALLOC(u8, tab, 512); u8* res = tab+256;
|
||||
usz ria = avx2_deduplicate_u8(tyany_ptr(x), n, res, tab);
|
||||
B r; i8* rp = m_tyarrv(&r, 1, ria, el2t(xe));
|
||||
memcpy(rp, res, ria);
|
||||
TFREE(tab); decG(x);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
return C2(slash, C1(memberOf, incG(x)), x);
|
||||
}
|
||||
|
||||
@ -111,10 +111,19 @@ def readbytes{vtab}{} = {
|
||||
# Stop early if the sum u reaches 0, indicating all bytes in the table
|
||||
# are equal: by the time it's checked at least one has been set to t,
|
||||
# so they're all t
|
||||
# If r0 is a pointer, set it to the unique mask of x0
|
||||
def do_bittab{x0:*void, n:u64, tab:*void, u:u8, t, r0} = {
|
||||
# Fill r0 depending on mode:
|
||||
# - 'none': ignore
|
||||
# - 'mask': Mark Firsts of x0
|
||||
# - 'unique': Deduplicate of x0
|
||||
def do_bittab{x0:*void, n:u64, tab:*void, u:u8, t, mode, r0} = {
|
||||
def rbit = mode == 'mask'
|
||||
def storebit{i, v:T} = if (rbit) store{*T~~r0, i, v}
|
||||
def rval = mode == 'unique'
|
||||
if (rbit or rval) assert{match{t,0}}
|
||||
|
||||
btab:= *i8~~tab
|
||||
def settab_sub{x, v} = {
|
||||
if (rval and v!=0) store{*u8~~r0, u, x}
|
||||
u+= u8~~(t - v) # u tracks the total of btab
|
||||
store{btab, x, t}
|
||||
v
|
||||
@ -123,9 +132,6 @@ def do_bittab{x0:*void, n:u64, tab:*void, u:u8, t, r0} = {
|
||||
def settab{x} = settab_sub{x, load{btab, x}} # General case
|
||||
def settab{T, x} = T~~promote{ty_s{T}, settab{x}}
|
||||
|
||||
def rbit = ~match{r0, 0}
|
||||
def storebit{i, v:T} = if (rbit) store{*T~~r0, i, v}
|
||||
|
||||
# Do first few values with a scalar loop
|
||||
# Avoids the cost of ever loading the table into vectors for n<=48
|
||||
x:= *u8~~x0
|
||||
@ -137,7 +143,7 @@ def do_bittab{x0:*void, n:u64, tab:*void, u:u8, t, r0} = {
|
||||
if (rbit) rw|= new & ((u64~~1)<<j)
|
||||
}
|
||||
storebit{0, rw}
|
||||
if (not rbit and u == 0) return{u} # Won't ever trigger (m != 0)!
|
||||
if (mode == 'none' and u == 0) return{u} # Won't ever trigger (m != 0)!
|
||||
|
||||
def done = makelabel{}
|
||||
def {bitsel, reload_tab} = bittab_selector{readbytes{*VI~~tab}}
|
||||
@ -187,11 +193,20 @@ fn avx2_mark_firsts_u8(x0:*void, n:u64, r0:*void, tab:*void) : void = {
|
||||
init:= VI**(-1)
|
||||
@unroll (t in *VI~~tab over 8) t = init
|
||||
u:u8 = 0
|
||||
do_bittab{x0, n, tab, u, 0, r0}
|
||||
do_bittab{x0, n, tab, u, 0, 'mask', r0}
|
||||
}
|
||||
|
||||
fn avx2_deduplicate_u8(x0:*void, n:u64, r0:*void, tab:*void) : u64 = {
|
||||
assert{n != 0}
|
||||
init:= VI**(-1)
|
||||
@unroll (t in *VI~~tab over 8) t = init
|
||||
u:u8 = 0
|
||||
do_bittab{x0, n, tab, u, 0, 'unique', r0}
|
||||
1 + promote{u64, u-1} # 0 to 256
|
||||
}
|
||||
|
||||
fn fill_bittab(x0:*void, n:u64, tab:*void, u:u8, t:i8) : u8 = {
|
||||
do_bittab{x0, n, tab, u, t, 0}
|
||||
do_bittab{x0, n, tab, u, t, 'none', 0}
|
||||
}
|
||||
|
||||
fn avx2_member_u8(w0:*void, nw:u64, x0:*void, nx:u64, r0:*void, tab:*void) : void = {
|
||||
@ -218,5 +233,6 @@ fn avx2_member_u8(w0:*void, nw:u64, x0:*void, nx:u64, r0:*void, tab:*void) : voi
|
||||
}
|
||||
|
||||
export{'avx2_mark_firsts_u8', avx2_mark_firsts_u8}
|
||||
export{'avx2_deduplicate_u8', avx2_deduplicate_u8}
|
||||
export{'avx2_member_u8', avx2_member_u8}
|
||||
} # hasarch{'AVX2'}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user