Data Parallelism: hyper and race

Use hyper/race for CPU-bound, independent work on large collections. Avoid shared mutable state inside the blocks. The overhead isn't worth it for tiny workloads.

# hyper: parallel processing that PRESERVES order
my @results = (1..100_000).hyper.grep(*.is-prime).map(* ** 2);
say @results.elems;

# race: parallel processing WITHOUT ordering guarantees (slightly faster)
my $count = (1..100_000).race.grep(*.is-prime).elems;
say $count;                            # 9592

# Tuning batch size and degree (number of workers)
my @big = (1..1_000_000).hyper(batch => 10_000, degree => 8).map({ $_ * 2 }).List;

# Parallel for loops
hyper for 1..8 -> $n { say "processing $n on thread {$*THREAD.id}" }   # 6.d: hyper/race prefixes on for
race  for ^4 { }

# Compare with sequential timing
my $t = now;
(1..200_000).grep(*.is-prime).elems;
say "sequential: {now - $t}";
$t = now;
(1..200_000).hyper.grep(*.is-prime).elems;
say "hyper: {now - $t}";