From 0e5b98c4912224b26aa6dc7a399fa9f57f4241dc Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Fri, 17 Mar 2023 14:00:29 -0400 Subject: [PATCH] Return max from AVX2 counting function --- src/builtins/slash.c | 31 ++++++++++++++++++++----------- src/singeli/src/count.singeli | 22 ++++++++++++++-------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/builtins/slash.c b/src/builtins/slash.c index ed82ed13..553fc8f4 100644 --- a/src/builtins/slash.c +++ b/src/builtins/slash.c @@ -85,6 +85,9 @@ #define SINGELI_FILE constrep #include "../utils/includeSingeli.h" + #define SINGELI_FILE count + #include "../utils/includeSingeli.h" + extern void (*const avx2_scan_pluswrap_u8)(uint8_t* v0,uint8_t* v1,uint64_t v2,uint8_t v3); extern void (*const avx2_scan_pluswrap_u16)(uint16_t* v0,uint16_t* v1,uint64_t v2,uint16_t v3); extern void (*const avx2_scan_pluswrap_u32)(uint32_t* v0,uint32_t* v1,uint64_t v2,uint32_t v3); @@ -850,15 +853,6 @@ B slash_c2(B t, B w, B x) { return c2rt(slash, w, x); } -#if SINGELI_AVX2 - #define SINGELI_FILE count - #include "../utils/includeSingeli.h" - #define SINGELI_COUNT_OR(N) \ - if (N==8) avx2_count_i8(t, (u8*)xp, xia); else -#else - #define SINGELI_COUNT_OR(N) -#endif - B slash_im(B t, B x) { if (!isArr(x) || RNK(x)!=1) thrM("/⁼: Argument must be an array"); u8 xe = TI(x,elType); @@ -912,10 +906,10 @@ B slash_im(B t, B x) { usz m=1<m/2) thrM("/⁼: Argument cannot contain negative numbers"); \ i32* rp; r = m_i32arrv(&rp, ria); for (usz i=0; i, a, b} def inc{ptr, ind, v} = store{ptr, ind, v + load{ptr, ind}} def inc{ptr, ind} = inc{ptr, ind, 1} -fn count{T}(tab:*usz, x:*ty_u{T}, n:u64) : u1 = { +# Write counts /⁼x to tab and return ⌈´x +fn count{T}(tab:*usz, x:*T, n:u64) : T = { def vbits = 256 def vec = vbits/width{T} def uT = ty_u{T} @@ -21,25 +22,30 @@ fn count{T}(tab:*usz, x:*ty_u{T}, n:u64) : u1 = { def block = (2048*8) / vbits # Target vectors per block def b_max = block + block/4 # Last block max length assert{b_max < 1< vec*b_max) r = vec*block b := r / vec # Vector case does b full vectors if it runs + rv:= b * vec r0:u64 = 0 # Elements actually handled by vector case - # Find range to check for suitability + # Find range to check for suitability; return a negative if found xv := *V~~x jv := load{xv}; mv := jv @for (xv over _ from 1 to b) { jv = min{jv, xv}; mv = max{mv, xv} } + @for (x over _ from rv to r) { if (x<0) return{x}; if (x>mx) mx=x } jt := fold{min, jv} - mt := fold{max, mv} - jt # Counts needed (last one's implicit) - if (jt < 0) return{1} # Negative number found! + mt := fold{max, mv} + if (jt < 0) return{jt} + if (mt > mx) mx = mt - if (mt <= 48) { - r0 = b * vec + nc := mt - jt # Number of counts to perform: last is implicit + if (nc <= 48) { + r0 = rv j0 := promote{u64, uT~~jt} # Starting count - m := promote{u64, uT~~mt} # Number of iterations + m := promote{u64, uT~~nc} # Number of iterations total := trunc{usz, r0} # To compute last count def count_each{js, num} = { j := @collect (k to num) js+k @@ -63,7 +69,7 @@ fn count{T}(tab:*usz, x:*ty_u{T}, n:u64) : u1 = { i += r x += r } - 0 + mx } export{'avx2_count_i8', count{i8}}