Data update

This commit is contained in:
Ingy döt Net 2023-12-16 21:33:55 -08:00
parent 35bcdeebf8
commit 74c69a0df6
2427 changed files with 31826 additions and 3468 deletions

View file

@ -1,7 +1,6 @@
#| Recursive, single-thread, single-pass, quicksort implementation
multi quicksort(@unsorted where @unsorted.elems < 2) { @unsorted }
multi quicksort(@unsorted) {
my $pivot = @unsorted.pick;
my %class{Order} is default([]) = @unsorted.classify: * cmp $pivot;
|samewith(%class{Less}), |%class{Same}, |samewith(%class{More})
#| Recursive, single-thread, random pivot, single-pass, quicksort implementation
multi quicksort(\a where a.elems < 2) { a }
multi quicksort(\a, \pivot = a.pick) {
my %prt{Order} is default([]) = a.classify: * cmp pivot;
|samewith(%prt{Less}), |%prt{Same}, |samewith(%prt{More})
}

View file

@ -1,9 +1,8 @@
#| 7-Line, recursive, parallel, single-pass, quicksort implementation
multi seven-line-quicksort-parallel(@unsorted where @unsorted.elems < 2) { @unsorted }
multi seven-line-quicksort-parallel(@unsorted) {
my $pivot = @unsorted.pick;
my %partitions{Order} is default([]) = @unsorted.classify( * cmp $pivot );
my Promise $less = start { samewith(%partitions{Less}) }
my $more = samewith(%partitions{More});
await $less andthen |$less.result, |%partitions{Same}, |$more;
#| Recursive, parallel, random pivot, single-pass, quicksort implementation
multi quicksort-parallel-naive(\a where a.elems < 2) { a }
multi quicksort-parallel-naive(\a, \pivot = a.pick) {
my %prt{Order} is default([]) = a.classify: * cmp pivot;
my Promise $less = start { samewith(%prt{Less}) }
my $more = samewith(%prt{More});
await $less andthen |$less.result, |%prt{Same}, |$more;
}

View file

@ -1,31 +1,22 @@
constant $BATCH-SIZE = 2**10;
my atomicint $worker = $*KERNEL.cpu-cores;
#| Recursive, parallel, tuned, single-pass, quicksort implementation
proto quicksort-parallel(| --> Positional) {*}
multi quicksort-parallel(@unsorted where @unsorted.elems < 2) { @unsorted }
multi quicksort-parallel(@unsorted) {
# separate unsorted input into Order Less, Same and More compared to a random $pivot
my $pivot = @unsorted.pick;
my %partitions{Order} is default([]) = @unsorted.classify( * cmp $pivot );
#| Recursive, parallel, batch tuned, single-pass, quicksort implementation
sub quicksort-parallel(@a, $batch = 2**9) {
return @a if @a.elems < 2;
# atomically decide if we sort the Less partition on a new thread
my $less =$worker > 0 &&
%partitions{Less}.elems > $BATCH-SIZE
?? (
$worker--;
start {
LEAVE $worker++;
samewith(%partitions{Less})
}
)
!! samewith(%partitions{Less});
# separate unsorted input into Order Less, Same and More compared to a random $pivot
my $pivot = @a.pick;
my %prt{Order} is default([]) = @a.classify( * cmp $pivot );
# decide if we sort the Less partition on a new thread
my $less = %prt{Less}.elems >= $batch
?? start { samewith(%prt{Less}, $batch) }
!! samewith(%prt{Less}, $batch);
# meanwhile use current thread for sorting the More partition
my $more = samewith(%partitions{More});
my $more = samewith(%prt{More}, $batch);
# if we went parallel, we need to await the result
await $less andthen $less = $less.result if $less ~~ Promise;
# concat all sorted partitions into a list and return
|$less, |%partitions{Same}, |$more;
|$less, |%prt{Same}, |$more;
}

View file

@ -1,17 +1,17 @@
say "x" x 10 ~ " Testing " ~ "x" x 10;
use Test;
my @functions-under-test = &quicksort, &quicksort-parallel-naive, &quicksort-parallel;
my @testcases =
() => (),
<a>.List => <a>.List,
<a a> => <a a>,
<a b> => <a b>,
<b a> => <a b>,
("b", "a", 3) => (3, "a", "b"),
<h b a c d f e g> => <a b c d e f g h>,
(2, 3, 1, 4, 5) => (1, 2, 3, 4, 5),
<a 🎮 3 z 4 🐧> => <a 🎮 3 z 4 🐧>.sort
;
my @implementations = &quicksort, &seven-line-quicksort-parallel, &quicksort-parallel;
plan @testcases.elems * @implementations.elems;
for @implementations -> &fun {
;
plan @testcases.elems * @functions-under-test.elems;
for @functions-under-test -> &fun {
say &fun.name;
is-deeply &fun(.key), .value, .key ~ " => " ~ .value for @testcases;
}

View file

@ -1,9 +1,28 @@
my $elem-length = 8;
my @large of Str = ('a'..'z').roll($elem-length).join xx 10 * $worker * $BATCH-SIZE;
say "x" x 11 ~ " Benchmarking " ~ "x" x 11;
use Benchmark;
my $runs = 5;
my $elems = 10 * Kernel.cpu-cores * 2**10;
my @unsorted of Str = ('a'..'z').roll(8).join xx $elems;
my UInt $l-batch = 2**13;
my UInt $m-batch = 2**11;
my UInt $s-batch = 2**9;
my UInt $t-batch = 2**7;
say "Benchmarking by sorting {@large.elems} strings of size $elem-length - using batches of $BATCH-SIZE strings and $worker workers.";
my @benchmark = gather for @implementations -> &fun {
&fun(@large);
take (&fun.name => now - ENTER now);
say "elements: $elems, runs: $runs, cpu-cores: {Kernel.cpu-cores}, large/medium/small/tiny-batch: $l-batch/$m-batch/$s-batch/$t-batch";
my %results = timethese $runs, {
single-thread => { quicksort(@unsorted) },
parallel-naive => { quicksort-parallel-naive(@unsorted) },
parallel-tiny-batch => { quicksort-parallel(@unsorted, $t-batch) },
parallel-small-batch => { quicksort-parallel(@unsorted, $s-batch) },
parallel-medium-batch => { quicksort-parallel(@unsorted, $m-batch) },
parallel-large-batch => { quicksort-parallel(@unsorted, $l-batch) },
}, :statistics;
my @metrics = <mean median sd>;
my $msg-row = "%.4f\t" x @metrics.elems ~ '%s';
say @metrics.join("\t");
for %results.kv -> $name, %m {
say sprintf($msg-row, %m{@metrics}, $name);
}
say @benchmark;