Seems the issue has more to do with running an empty loop, rather than
performing a real computation.
This is a run on a 4-core box. Attempting to parallelize an empty loop makes
the execution 1 second slower:
my &code = { for ^2_000_000 { } };
my $start = now; (^4).map: &code; my $stop = now;
say "Serial: {$stop - $start}";
$start = now; await (^4).map: {start code}; $stop = now;
say "Parallel: {$stop - $start}";
# Serial: 1.5161628
# Parallel: 2.56597794
But running actual real-life code makes it almost 4 times faster, as
would be expected on a 4-core box:
use Crypt::Bcrypt;
my &code = { bcrypt-hash ~rand, :15rounds; };
my $start = now; (^4).map: &code; my $stop = now;
say "Serial: {$stop - $start}";
$start = now; await (^4).map: {start code}; $stop = now;
say "Parallel: {$stop - $start}";
# Serial: 7.69045687
# Parallel: 2.087147
On Sat Oct 01 06:15:18 2016, [email protected] wrote:
> This could be a stupid user problem, in which case I apologise for wasting
> your time.
>
> Simple concurrency demonstrations seem to work; the following completes in
> just over a second:
>
> perl6 -e 'await Promise.allof(start {sleep 1}, start {sleep 1}, start
> {sleep 1});say now - INIT now'
>
> However if the started tasks are doing any CPU-intensive work, they seem
> to take much longer than if they had been run sequentially, without using
> promises at all.
>
> To reproduce the issue, please run this script.
>
> -----
> use v6;
>
> my $r = 2_000_000;
>
> say "Counting to $r";
>
> my ($start, $setup, $stop);
> $start = now;
> {
> my ($i, $j);
> $j = $r;
> loop ($i = 0; $i < $j; $i++) { }
> }
> $stop = now;
>
> say "Non-promise iteration: {$stop - $start}";
>
> my @promises;
> $start = now;
> @promises.push(start {
> my ($i, $j);
> $j = $r;
> loop ($i = 0; $i < $j; $i++) { }
> });
> $setup = now;
> await Promise.allof(@promises);
> $stop = now;
>
> say "One iteration: {$stop - $start} (setup: {$setup - $start})";
>
> @promises = ();
>
> $start = now;
> for (1..16) {
> @promises.push(start {
> my ($i, $j);
> $j = $r;
> loop ($i = 0; $i < $j; $i++) { }
> });
> }
> $setup = now;
> await Promise.allof(@promises);
> $stop = now;
>
> say "16 iterations: {$stop - $start} (setup: {$setup - $start})";
> -----
>
> What I expected:
>
> One iteration would take roughly the same amount of time as the
> non-promise iteration (the sleep example above would suggest that the
> threading overhead would be less than 0.001s)
>
> 16 iterations would take, at worst, about 16 times as long as the line
> 'one iteration' above it.
>
> What happens:
>
> On a Windows 10 PC, with 6 cores (12 logical processors)
>
> C:\Users\Steve>perl6 concurrency-wtf.pl
> Counting to 2000000
> Non-promise iteration: 0.6162481
> One iteration: 2.23909643 (setup: 0.00300325)
> 16 iterations: 65.56993665 (setup: 0.00700654)
>
> On an Ubuntu 14.04.5 LTS PC, with 2 cores
>
> steve@prole:~/$ perl6 concurrency-wtf.pl
> Counting to 2000000
> Non-promise iteration: 0.6948201
> One iteration: 1.9678549 (setup: 0.0024696)
> 16 iterations: 107.1483633 (setup: 0.0474610)
>
> Also the CPU usage leaps 100% (all CPUs, all at 100%) while running, on
> both PCs. The PCs are mostly idle otherwise (Windows 10 - about 3%
> utilization, Linux - 199% idle)
>
> Perl 6 version
>
> C:\Users\Steve>perl6 -v
> This is Rakudo version 2016.07.1 built on MoarVM version 2016.07
> implementing Perl 6.c.
>
> steve@prole:~/$ perl6 -v
> This is Rakudo version 2016.07.1 built on MoarVM version 2016.07
> implementing Perl 6.c.