From bc7275a91b0b54ac05ad518ac3e697a113eadcd9 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 1 May 2023 21:22:52 -0400 Subject: [PATCH 01/10] Basic MergeShuffle implementation (slow merge) --- src/builtins/sysfn.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index c1197309..712ee0f3 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -431,13 +431,43 @@ B rand_deal_c1(B t, B x) { if (xi==0) return emptyIVec(); RAND_START; i32* rp; B r = m_i32arrv(&rp, xi); - for (i64 i = 0; i < xi; i++) rp[i] = i; - for (i64 i = 0; i < xi; i++) { - i32 j = wy2u0k(wyrand(&seed), xi-i) + i; - i32 c = rp[j]; - rp[j] = rp[i]; - rp[i] = c; + + // MergeShuffle + usz sh = 0; + usz thr = 1<<24; + while ((xi >> sh) > thr) sh++; + usz q = 1 << sh; + u64 n = xi; + + for (usz p = 0, i = 0; p < q; p++) { + usz e = (n*(p+1)) >> sh; + for (usz k = i; k < e; k++) rp[k] = k; + for (; i < e; i++) { + usz j = wy2u0k(wyrand(&seed), e-i) + i; + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; + } } + + for (usz w = 1; w < q; w <<= 1) { + usz i = 0; + for (usz p = 0; p < q; p += 2*w) { + usz t = i; + usz j = (n*(p + w)) >> sh; + usz e = (n*(p + 2*w)) >> sh; + u64 r = wyrand(&seed); // Random bits + while (1) { + u64 bit = r&1; r>>=1; + if (bit) { if (j == e) break; usz c=rp[i]; rp[i]=rp[j]; rp[j]=c; j++; } + else { if (i == j) break; } + if (++i%64==0) r = wyrand(&seed); + } + for (; i < e; i++) { + usz j = wy2u0k(wyrand(&seed), 1+i-t) + t; + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; + } + } + } + RAND_END; return r; } From 8191aa6da282a55f7232e8d15d9f5eff46f4a5bb Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 1 May 2023 21:49:40 -0400 Subject: [PATCH 02/10] Only iterate over set bits in random merge --- src/builtins/sysfn.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 712ee0f3..87f168da 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -434,7 +434,7 @@ B rand_deal_c1(B t, B x) { // MergeShuffle usz sh = 0; - usz thr = 1<<24; + usz thr = 1<<18; while ((xi >> sh) > thr) sh++; usz q = 1 << sh; u64 n = xi; @@ -454,13 +454,16 @@ B rand_deal_c1(B t, B x) { usz t = i; usz j = (n*(p + w)) >> sh; usz e = (n*(p + 2*w)) >> sh; - u64 r = wyrand(&seed); // Random bits - while (1) { - u64 bit = r&1; r>>=1; - if (bit) { if (j == e) break; usz c=rp[i]; rp[i]=rp[j]; rp[j]=c; j++; } - else { if (i == j) break; } - if (++i%64==0) r = wyrand(&seed); + for (usz i0 = i; ; i0 += 64) { + for (u64 r = wyrand(&seed); r; r&=r-1) { + i = i0 + CTZ(r); + if (i > j) { i=j; goto tail; } + if (j == e) goto tail; + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; + j++; + } } + tail: for (; i < e; i++) { usz j = wy2u0k(wyrand(&seed), 1+i-t) + t; usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; From 6cc9d404900703c165ea41b3d2117d307baaa865 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Wed, 3 May 2023 21:16:32 -0400 Subject: [PATCH 03/10] =?UTF-8?q?Fast=20cases=20for=20short=20=E2=80=A2ran?= =?UTF-8?q?d.Deal=F0=9D=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/sysfn.c | 95 ++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 87f168da..3ecf7a9d 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -425,52 +425,68 @@ B rand_range_c2(B t, B w, B x) { return taga(r); } +extern Arr* bitUD[3]; // from fns.c +extern B bit2x[2]; B rand_deal_c1(B t, B x) { i32 xi = o2i(x); - if (RARE(xi<0)) thrM("(rand).Deal: Argument cannot be negative"); - if (xi==0) return emptyIVec(); - RAND_START; - i32* rp; B r = m_i32arrv(&rp, xi); - - // MergeShuffle - usz sh = 0; - usz thr = 1<<18; - while ((xi >> sh) > thr) sh++; - usz q = 1 << sh; - u64 n = xi; - - for (usz p = 0, i = 0; p < q; p++) { - usz e = (n*(p+1)) >> sh; - for (usz k = i; k < e; k++) rp[k] = k; - for (; i < e; i++) { - usz j = wy2u0k(wyrand(&seed), e-i) + i; - usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; - } + if (RARE(xi<=1)) { + if (xi<0) thrM("(rand).Deal: Argument cannot be negative"); + return xi==0? emptyIVec() : taga(ptr_inc(bitUD[xi])); } - for (usz w = 1; w < q; w <<= 1) { - usz i = 0; - for (usz p = 0; p < q; p += 2*w) { - usz t = i; - usz j = (n*(p + w)) >> sh; - usz e = (n*(p + 2*w)) >> sh; - for (usz i0 = i; ; i0 += 64) { - for (u64 r = wyrand(&seed); r; r&=r-1) { - i = i0 + CTZ(r); - if (i > j) { i=j; goto tail; } - if (j == e) goto tail; - usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; - j++; - } - } - tail: + RAND_START; + B r; + if (xi == 2) { + r = incG(bit2x[wyrand(&seed)&1]); + } else if (LIKELY(xi <= 128)) { + i8* rp; r = m_i8arrv(&rp, xi); + for (usz i = 0; i < xi; i++) rp[i] = i; + for (usz i = 0; i < xi-1; i++) { + usz j = wy2u0k(wyrand(&seed), xi-i) + i; + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; + } + } else { + i32* rp; r = m_i32arrv(&rp, xi); + + // MergeShuffle + usz sh = 0; + usz thr = 1<<18; + while ((xi >> sh) > thr) sh++; + usz q = 1 << sh; + u64 n = xi; + + for (usz p = 0, i = 0; p < q; p++) { + usz e = (n*(p+1)) >> sh; + for (usz k = i; k < e; k++) rp[k] = k; for (; i < e; i++) { - usz j = wy2u0k(wyrand(&seed), 1+i-t) + t; + usz j = wy2u0k(wyrand(&seed), e-i) + i; usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; } } - } + for (usz w = 1; w < q; w <<= 1) { + usz i = 0; + for (usz p = 0; p < q; p += 2*w) { + usz t = i; + usz j = (n*(p + w)) >> sh; + usz e = (n*(p + 2*w)) >> sh; + for (usz i0 = i; ; i0 += 64) { + for (u64 r = wyrand(&seed); r; r&=r-1) { + i = i0 + CTZ(r); + if (i > j) { i=j; goto tail; } + if (j == e) goto tail; + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; + j++; + } + } + tail: + for (; i < e; i++) { + usz j = wy2u0k(wyrand(&seed), 1+i-t) + t; + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; + } + } + } + } RAND_END; return r; } @@ -478,10 +494,11 @@ B rand_deal_c1(B t, B x) { B rand_deal_c2(B t, B w, B x) { i32 wi = o2i(w); i32 xi = o2i(x); - if (RARE(wi<0)) thrM("(rand).Deal: 𝕨 cannot be negative"); if (RARE(xi<0)) thrM("(rand).Deal: 𝕩 cannot be negative"); - if (RARE(wi>xi)) thrM("(rand).Deal: 𝕨 cannot exceed 𝕩"); + if (RARE(wi<0)) thrM("(rand).Deal: 𝕨 cannot be negative"); if (wi==0) return emptyIVec(); + if (RARE(wi>xi)) thrM("(rand).Deal: 𝕨 cannot exceed 𝕩"); + if (wi==xi) return rand_deal_c1(t, x); B r; RAND_START; if (wi > xi/64) { From a4f9d237098694d0dd955354a223dec307343df5 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Thu, 4 May 2023 10:18:38 -0400 Subject: [PATCH 04/10] Simplify merge-shuffle index usage --- src/builtins/sysfn.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 3ecf7a9d..4440f5b7 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -449,14 +449,13 @@ B rand_deal_c1(B t, B x) { i32* rp; r = m_i32arrv(&rp, xi); // MergeShuffle - usz sh = 0; - usz thr = 1<<18; - while ((xi >> sh) > thr) sh++; - usz q = 1 << sh; u64 n = xi; + usz log2 = 64 - CLZ(n-1); + usz thr = 18; + usz sh = log2<=thr? 0 : log2-thr; - for (usz p = 0, i = 0; p < q; p++) { - usz e = (n*(p+1)) >> sh; + for (u64 es = n, i = 0; i < n; es += n) { + usz e = es >> sh; for (usz k = i; k < e; k++) rp[k] = k; for (; i < e; i++) { usz j = wy2u0k(wyrand(&seed), e-i) + i; @@ -464,12 +463,12 @@ B rand_deal_c1(B t, B x) { } } - for (usz w = 1; w < q; w <<= 1) { + for (; sh > 0; sh--) { usz i = 0; - for (usz p = 0; p < q; p += 2*w) { + for (u64 es = 2*n; i < n; es += 2*n) { usz t = i; - usz j = (n*(p + w)) >> sh; - usz e = (n*(p + 2*w)) >> sh; + usz j = (es - n) >> sh; + usz e = es >> sh; for (usz i0 = i; ; i0 += 64) { for (u64 r = wyrand(&seed); r; r&=r-1) { i = i0 + CTZ(r); From 2b9c193f24e97f32c3686826a1edd41dad260e6a Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Thu, 4 May 2023 14:04:10 -0400 Subject: [PATCH 05/10] =?UTF-8?q?Outer=20split=20pass=20for=20large=20?= =?UTF-8?q?=E2=80=A2rand.Deal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/sysfn.c | 130 ++++++++++++++++++++++++++++++------------- 1 file changed, 92 insertions(+), 38 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 4440f5b7..7b91dec5 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -425,6 +425,50 @@ B rand_range_c2(B t, B w, B x) { return taga(r); } +// MergeShuffle +static void merge_shuffle(i32* rp, i32* sp, u64 n, u64* pseed) { + u64 seed = *pseed; + usz log2 = 64 - CLZ(n-1); + usz thr = 20; + usz sh = log2<=thr? 0 : log2-thr; + + bool init = sp==NULL; + if (init) sp = rp; + + usz i = 0; for (u64 es = n; i < n; es += n) { + usz e = es >> sh; + if (init) for (usz k = i; k < e; k++) rp[k] = k; + for (; i < e; i++) { + usz j = wy2u0k(wyrand(&seed), e-i) + i; + usz c=sp[j]; sp[j]=sp[i]; rp[i]=c; + } + } + + for (; sh > 0; sh--) { + usz i = 0; + for (u64 es = 2*n; i < n; es += 2*n) { + usz t = i; + usz j = (es - n) >> sh; + usz e = es >> sh; + for (usz i0 = i; ; i0 += 64) { + for (u64 r = wyrand(&seed); r; r&=r-1) { + i = i0 + CTZ(r); + if (i > j) { i=j; goto tail; } + if (j == e) goto tail; + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; + j++; + } + } + tail: + for (; i < e; i++) { + usz j = wy2u0k(wyrand(&seed), 1+i-t) + t; + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; + } + } + } + *pseed = seed; +} + extern Arr* bitUD[3]; // from fns.c extern B bit2x[2]; B rand_deal_c1(B t, B x) { @@ -439,51 +483,61 @@ B rand_deal_c1(B t, B x) { if (xi == 2) { r = incG(bit2x[wyrand(&seed)&1]); } else if (LIKELY(xi <= 128)) { + #define SHUF \ + for (usz i = 0; i < xi; i++) rp[i] = i; \ + for (usz i = 0; i < xi-1; i++) { \ + usz j = wy2u0k(wyrand(&seed), xi-i) + i; \ + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; \ + } i8* rp; r = m_i8arrv(&rp, xi); - for (usz i = 0; i < xi; i++) rp[i] = i; - for (usz i = 0; i < xi-1; i++) { - usz j = wy2u0k(wyrand(&seed), xi-i) + i; - usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; - } + SHUF + } else if (LIKELY(xi <= 1<<15)) { + i16* rp; r = m_i16arrv(&rp, xi); + SHUF + #undef SHUF } else { i32* rp; r = m_i32arrv(&rp, xi); - - // MergeShuffle u64 n = xi; - usz log2 = 64 - CLZ(n-1); - usz thr = 18; - usz sh = log2<=thr? 0 : log2-thr; - - for (u64 es = n, i = 0; i < n; es += n) { - usz e = es >> sh; - for (usz k = i; k < e; k++) rp[k] = k; - for (; i < e; i++) { - usz j = wy2u0k(wyrand(&seed), e-i) + i; - usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; - } - } - - for (; sh > 0; sh--) { + if (n <= 1<<19) { + merge_shuffle(rp, NULL, n, &seed); + } else { + // Initial split pass like a random radix sort + // Don't count partition size exactly; instead, assume lengths + // are within 1 and stop when a partition is full + // Shuffle leftovers in at the end + usz log2 = 64 - CLZ(n-1); + usz thr = 16; + usz sd = log2> sd; usz i = 0; - for (u64 es = 2*n; i < n; es += 2*n) { - usz t = i; - usz j = (es - n) >> sh; - usz e = es >> sh; - for (usz i0 = i; ; i0 += 64) { - for (u64 r = wyrand(&seed); r; r&=r-1) { - i = i0 + CTZ(r); - if (i > j) { i=j; goto tail; } - if (j == e) goto tail; - usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; - j++; - } - } - tail: - for (; i < e; i++) { - usz j = wy2u0k(wyrand(&seed), 1+i-t) + t; - usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; + while (1) { + u64 r = wyrand(&seed) & mm; + for (usz j = 0; j < 8; j++) { + u8 k = r; r>>= 8; + usz* pp = pos+2*k; + usz p = pp[0]; + if (p == pp[1]) goto split_done; + pp[0]++; + rp[p] = i++; } } + split_done: + for (usz p=0, j=0, s=0; p Date: Thu, 4 May 2023 18:10:26 -0400 Subject: [PATCH 06/10] =?UTF-8?q?Remove=20MergeShuffle:=20only=20used=20ab?= =?UTF-8?q?ove=202=E2=8B=8628=20with=20split=20and=20not=20a=20huge=20spee?= =?UTF-8?q?dup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/sysfn.c | 75 +++++++++++--------------------------------- 1 file changed, 18 insertions(+), 57 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 7b91dec5..dc380322 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -425,50 +425,6 @@ B rand_range_c2(B t, B w, B x) { return taga(r); } -// MergeShuffle -static void merge_shuffle(i32* rp, i32* sp, u64 n, u64* pseed) { - u64 seed = *pseed; - usz log2 = 64 - CLZ(n-1); - usz thr = 20; - usz sh = log2<=thr? 0 : log2-thr; - - bool init = sp==NULL; - if (init) sp = rp; - - usz i = 0; for (u64 es = n; i < n; es += n) { - usz e = es >> sh; - if (init) for (usz k = i; k < e; k++) rp[k] = k; - for (; i < e; i++) { - usz j = wy2u0k(wyrand(&seed), e-i) + i; - usz c=sp[j]; sp[j]=sp[i]; rp[i]=c; - } - } - - for (; sh > 0; sh--) { - usz i = 0; - for (u64 es = 2*n; i < n; es += 2*n) { - usz t = i; - usz j = (es - n) >> sh; - usz e = es >> sh; - for (usz i0 = i; ; i0 += 64) { - for (u64 r = wyrand(&seed); r; r&=r-1) { - i = i0 + CTZ(r); - if (i > j) { i=j; goto tail; } - if (j == e) goto tail; - usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; - j++; - } - } - tail: - for (; i < e; i++) { - usz j = wy2u0k(wyrand(&seed), 1+i-t) + t; - usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; - } - } - } - *pseed = seed; -} - extern Arr* bitUD[3]; // from fns.c extern B bit2x[2]; B rand_deal_c1(B t, B x) { @@ -480,31 +436,30 @@ B rand_deal_c1(B t, B x) { RAND_START; B r; + #define SHUF \ + for (usz i = 0; i < xi; i++) rp[i] = i; \ + for (usz i = 0; i < xi-1; i++) { \ + usz j = wy2u0k(wyrand(&seed), xi-i) + i; \ + usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; \ + } if (xi == 2) { r = incG(bit2x[wyrand(&seed)&1]); } else if (LIKELY(xi <= 128)) { - #define SHUF \ - for (usz i = 0; i < xi; i++) rp[i] = i; \ - for (usz i = 0; i < xi-1; i++) { \ - usz j = wy2u0k(wyrand(&seed), xi-i) + i; \ - usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; \ - } i8* rp; r = m_i8arrv(&rp, xi); SHUF } else if (LIKELY(xi <= 1<<15)) { i16* rp; r = m_i16arrv(&rp, xi); SHUF - #undef SHUF } else { i32* rp; r = m_i32arrv(&rp, xi); - u64 n = xi; - if (n <= 1<<19) { - merge_shuffle(rp, NULL, n, &seed); + if (xi <= 1<<19) { + SHUF } else { // Initial split pass like a random radix sort // Don't count partition size exactly; instead, assume lengths // are within 1 and stop when a partition is full // Shuffle leftovers in at the end + u64 n = xi; usz log2 = 64 - CLZ(n-1); usz thr = 16; usz sd = log2 Date: Fri, 5 May 2023 12:18:31 +0300 Subject: [PATCH 07/10] merge emptyIVec() case with bitUD[0] --- src/builtins/sysfn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index dc380322..8cbd3568 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -431,7 +431,7 @@ B rand_deal_c1(B t, B x) { i32 xi = o2i(x); if (RARE(xi<=1)) { if (xi<0) thrM("(rand).Deal: Argument cannot be negative"); - return xi==0? emptyIVec() : taga(ptr_inc(bitUD[xi])); + return taga(ptr_inc(bitUD[xi])); } RAND_START; From 65d0b829bd077e9205fc87507b198afe7afbce3b Mon Sep 17 00:00:00 2001 From: dzaima Date: Fri, 5 May 2023 12:40:23 +0300 Subject: [PATCH 08/10] =?UTF-8?q?reuse=20range=20generation=20from=20?= =?UTF-8?q?=E2=86=95n=20for=20=E2=80=A2rand.Deal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/fns.c | 34 ++++++++++++++++++---------------- src/builtins/sysfn.c | 10 +++++++--- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/builtins/fns.c b/src/builtins/fns.c index 026fdb3a..13e80b6d 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -7,23 +7,18 @@ #include "../nfns.h" - -NOINLINE B intRange(ux s, ux n) { // intended for s+n≥128; assumes n≥1 - assert(n>0); - ux last = n+s-1; - if (last<=I16_MAX) { - i16* rp; B r = m_i16arrv(&rp, n); - for (ux i = 0; i < n; i++) rp[i] = (i16)s + (i16)i; - return r; - } - if (last<=I32_MAX) { - i32* rp; B r = m_i32arrv(&rp, n); - for (ux i = 0; i < n; i++) rp[i] = (i32)s + (i32)i; - return r; - } - +NOINLINE B intRange16(ux s, ux n) { // s+↕n with i16arr result + i16* rp; B r = m_i16arrv(&rp, n); + for (ux i = 0; i < n; i++) rp[i] = (i16)s + (i16)i; + return r; +} +NOINLINE B intRange32(ux s, ux n) { // s+↕n with i32arr result + i32* rp; B r = m_i32arrv(&rp, n); + for (ux i = 0; i < n; i++) rp[i] = (i32)s + (i32)i; + return r; +} +NOINLINE B intRangeF64(ux s, ux n) { // s+↕n with f64arr result f64* rp; B r = m_f64arrv(&rp, n); - f64 c = s; PLAINLOOP for (ux i = 0; i < n/16; i++) { for (ux j = 0; j < 16; j++) rp[j] = c+j; @@ -33,6 +28,13 @@ NOINLINE B intRange(ux s, ux n) { // intended for s+n≥128; assumes n≥1 for (ux j = 0; j < (n&15); j++) rp[j] = c+j; return r; } +B intRange(ux s, ux n) { // intended for s+n≥128; assumes n≥1 + assert(n>0); + ux last = n+s-1; + if (last<=I16_MAX) return intRange16(s, n); + if (last<=I32_MAX) return intRange32(s, n); + return intRangeF64(s, n); +} static B* ud_rec(B* p, usz d, usz r, i32* pos, usz* sh) { usz cl = sh[d]; diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 8cbd3568..219130b6 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -427,6 +427,9 @@ B rand_range_c2(B t, B w, B x) { extern Arr* bitUD[3]; // from fns.c extern B bit2x[2]; +NOINLINE B intRange16(ux s, ux n); +NOINLINE B intRange32(ux s, ux n); + B rand_deal_c1(B t, B x) { i32 xi = o2i(x); if (RARE(xi<=1)) { @@ -437,7 +440,6 @@ B rand_deal_c1(B t, B x) { RAND_START; B r; #define SHUF \ - for (usz i = 0; i < xi; i++) rp[i] = i; \ for (usz i = 0; i < xi-1; i++) { \ usz j = wy2u0k(wyrand(&seed), xi-i) + i; \ usz c=rp[j]; rp[j]=rp[i]; rp[i]=c; \ @@ -446,15 +448,17 @@ B rand_deal_c1(B t, B x) { r = incG(bit2x[wyrand(&seed)&1]); } else if (LIKELY(xi <= 128)) { i8* rp; r = m_i8arrv(&rp, xi); + NOUNROLL for (usz i = 0; i < xi; i++) rp[i] = i; SHUF } else if (LIKELY(xi <= 1<<15)) { - i16* rp; r = m_i16arrv(&rp, xi); + r = intRange16(0, xi); i16* rp = i16arr_ptr(r); SHUF } else { - i32* rp; r = m_i32arrv(&rp, xi); if (xi <= 1<<19) { + r = intRange32(0, xi); i32* rp = i32arr_ptr(r); SHUF } else { + i32* rp; r = m_i32arrv(&rp, xi); // Initial split pass like a random radix sort // Don't count partition size exactly; instead, assume lengths // are within 1 and stop when a partition is full From 14ca835fa24c1ed59c30c28d4c1e921a170b786a Mon Sep 17 00:00:00 2001 From: dzaima Date: Fri, 5 May 2023 13:23:47 +0300 Subject: [PATCH 09/10] don't unroll comparatively extremely tiny loop --- src/builtins/sysfn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 219130b6..1a302397 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -471,7 +471,7 @@ B rand_deal_c1(B t, B x) { u64 mm = 0x0101010101010101ull * (m-1); TALLOC(usz, pos, 2*m) // Current and ending positions pos[0] = 0; pos[2*m-1] = n; - for (usz p=1; p> sd; + PLAINLOOP for (usz p=1; p> sd; usz i = 0; while (1) { u64 r = wyrand(&seed) & mm; From cc94ec4cbcc7bc0775c87fea874314f5c9f38198 Mon Sep 17 00:00:00 2001 From: dzaima Date: Fri, 5 May 2023 13:28:58 +0300 Subject: [PATCH 10/10] =?UTF-8?q?move=20out=20another=20s+=E2=86=95n=20loo?= =?UTF-8?q?p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/fns.c | 5 ++++- src/builtins/sysfn.c | 7 ++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/builtins/fns.c b/src/builtins/fns.c index 13e80b6d..79fd7a63 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -12,9 +12,12 @@ NOINLINE B intRange16(ux s, ux n) { // s+↕n with i16arr result for (ux i = 0; i < n; i++) rp[i] = (i16)s + (i16)i; return r; } +NOINLINE void intRange32Fill(i32* xp, ux s, ux n) { // fill xp with s+↕n + for (ux i = 0; i < n; i++) xp[i] = (i32)s + (i32)i; +} NOINLINE B intRange32(ux s, ux n) { // s+↕n with i32arr result i32* rp; B r = m_i32arrv(&rp, n); - for (ux i = 0; i < n; i++) rp[i] = (i32)s + (i32)i; + intRange32Fill(rp, s, n); return r; } NOINLINE B intRangeF64(ux s, ux n) { // s+↕n with f64arr result diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 1a302397..4d38f530 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -427,8 +427,9 @@ B rand_range_c2(B t, B w, B x) { extern Arr* bitUD[3]; // from fns.c extern B bit2x[2]; -NOINLINE B intRange16(ux s, ux n); -NOINLINE B intRange32(ux s, ux n); +B intRange16(ux s, ux n); +B intRange32(ux s, ux n); +void intRange32Fill(i32* xp, ux s, ux n); B rand_deal_c1(B t, B x) { i32 xi = o2i(x); @@ -497,7 +498,7 @@ B rand_deal_c1(B t, B x) { b+= l; } TFREE(pos) - for (usz j=i; j