-
-
Save FROGGS/0cfae647d28c493df73e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
time nqp add-i-mt.t | |
real 0m54.993s | |
user 2m37.112s | |
sys 0m3.308s | |
time nqp aplusb.nqp | |
real 0m27.060s | |
user 0m30.508s | |
sys 0m1.424s |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use QAST; | |
plan(1); | |
sub is_pirt_result($producer, $expected, $desc) { | |
my $pirt := $producer(); | |
my $pir := $pirt.pir(); | |
my $pbc := nqp::getcomp('nqp').compile($pir, :from('pir')); | |
$pbc := $pbc(); | |
if nqp::islist($pbc) { | |
my $a := join(', ', $pbc); | |
my $b := join(', ', $expected); | |
say("expected: [$b]\n got: [$a]") unless $a eq $b; | |
ok($a eq $b, $desc); | |
} | |
else { | |
ok($pbc eq $expected, $desc); | |
} | |
} | |
my @c; | |
is_pirt_result({ | |
my $a := 0; | |
my $b := 0; | |
nqp::push(@c, $a := $a + 2) while $a < 180_000; | |
$a := 0; | |
# create a proxy (green thread) that will write to a shared variable | |
my $write_ops := PIRT::Ops.new(); | |
$write_ops.push_pirop(".param pmc results"); | |
$write_ops.push_pirop(".local pmc interp, task, offset, number"); | |
$write_ops.push_pirop("interp = getinterp"); | |
$write_ops.push_pirop("task = interp.'current_task'()"); | |
$write_ops.push_pirop("number = pop task"); | |
$write_ops.push_pirop("offset = pop task"); | |
$write_ops.push_pirop("results[offset] = number"); | |
my $write_sub := PIRT::Sub.new(); | |
$write_sub.push($write_ops); | |
$write_sub.subid('write_to_variable'); | |
# create the op itself | |
my $add_i_ops := PIRT::Ops.new(); | |
$add_i_ops.push($write_sub); | |
$add_i_ops.push_pirop(".param pmc offset"); | |
$add_i_ops.push_pirop(".local pmc interp, task, results, array_a, array_b, write_task, number, write_to_variable"); | |
$add_i_ops.push_pirop(".local int a, b, c"); | |
$add_i_ops.push_pirop("interp = getinterp"); | |
$add_i_ops.push_pirop("task = interp.'current_task'()"); | |
$add_i_ops.push_pirop("array_b = pop task"); | |
$add_i_ops.push_pirop("array_a = pop task"); | |
$add_i_ops.push_pirop("results = pop task"); | |
$add_i_ops.push_pirop("a = array_a[offset]"); | |
$add_i_ops.push_pirop("b = array_b[offset]"); | |
$add_i_ops.push_pirop("c = add a, b"); | |
$add_i_ops.push_pirop("number = new ['Integer']"); | |
$add_i_ops.push_pirop("number = c"); | |
$add_i_ops.push_pirop("write_task = new ['Task']"); | |
$add_i_ops.push_pirop("push write_task, offset"); | |
$add_i_ops.push_pirop("push write_task, number"); | |
$add_i_ops.push_pirop(".const 'Sub' \$P0 = 'write_to_variable'"); | |
$add_i_ops.push_pirop("setattribute write_task, 'code', \$P0"); | |
$add_i_ops.push_pirop("setattribute write_task, 'data', results"); | |
$add_i_ops.push_pirop("interp.'schedule_proxied'(write_task, results)"); | |
$add_i_ops.push_pirop("wait write_task"); | |
my $add_i_sub := PIRT::Sub.new(); | |
$add_i_sub.push($add_i_ops); | |
$add_i_sub.subid('add_i'); | |
# the main sub, it iterates over the input arrays and creates threads (tasks) | |
my $ops := PIRT::Ops.new(); | |
$ops.push($add_i_sub); | |
$ops.push_pirop(".local pmc task, operation, starter, offset, end, interp, tasks, results, array_a, array_b, number"); | |
$ops.push_pirop(".local int offset_i"); | |
$ops.push_pirop("tasks = new ['ResizablePMCArray']"); | |
$ops.push_pirop("results = new ['ResizablePMCArray']"); | |
$ops.push_pirop("array_a = new ['ResizablePMCArray']"); | |
$ops.push_pirop("array_b = new ['ResizablePMCArray']"); | |
$ops.push_pirop("push array_a, " ~ ($a := $a + 1)) while $a < 300_000; | |
$ops.push_pirop("push array_b, " ~ ($b := $b + 1)) while $b < 300_000; | |
$ops.push_pirop("offset = new ['Integer']"); | |
$ops.push_pirop("offset = 0"); | |
$ops.push_pirop("end = new ['Integer']"); | |
$ops.push_pirop("end = 289999"); | |
$ops.push_pirop("number = new ['Integer']"); | |
$ops.push_pirop("offset_i = offset"); | |
$ops.push_pirop("spawn_tasks:"); | |
$ops.push_pirop("task = new ['Task']"); | |
$ops.push_pirop("push task, results"); | |
$ops.push_pirop("push task, array_a"); | |
$ops.push_pirop("push task, array_b"); | |
$ops.push_pirop(".const 'Sub' \$P0 = 'add_i'"); | |
$ops.push_pirop("setattribute task, 'code', \$P0"); | |
$ops.push_pirop("number = new ['Integer']"); | |
$ops.push_pirop("number = offset_i"); | |
$ops.push_pirop("setattribute task, 'data', number"); | |
$ops.push_pirop("push tasks, task"); | |
$ops.push_pirop("schedule task"); | |
$ops.push_pirop("inc offset_i"); | |
$ops.push_pirop("if end >= offset_i goto spawn_tasks"); | |
$ops.push_pirop("offset_i = offset"); | |
$ops.push_pirop("join_tasks:"); | |
$ops.push_pirop("task = tasks[offset_i]"); | |
$ops.push_pirop("wait task"); | |
$ops.push_pirop("inc offset_i"); | |
$ops.push_pirop("if end >= offset_i goto join_tasks"); | |
$ops.push_pirop(".return (results)"); | |
my $sub := PIRT::Sub.new(); | |
$sub.push($ops); | |
$sub | |
}, | |
@c, | |
"add_i_MT"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sub aplusb($a, $b) { | |
$a + $b ** 3 / ($a + 2) * 47.5 | |
} | |
sub ed_green_thread() { Q:PIR { | |
.local pmc interp, task, block, block_name, result | |
.local string name | |
aplusb(2, 12) | |
} }; | |
sub ed_os_thread() { Q:PIR { | |
.param pmc block_name2 | |
.local pmc block_name | |
.local pmc interp, task, write_task, result | |
interp = getinterp | |
task = interp.'current_task'() | |
block_name = pop task | |
write_task = new ['Task'] | |
.const 'Sub' $P0 = 'ed_green_thread' | |
setattribute write_task, 'code', $P0 | |
interp.'schedule_proxied'(write_task, block_name) | |
} }; | |
sub exec_delayed() { Q:PIR { | |
.param pmc block_name | |
.local pmc task, interp | |
interp = getinterp | |
task = new ['Task'] | |
push task, block_name | |
.const 'Sub' $P0 = 'ed_os_thread' | |
setattribute task, 'code', $P0 | |
schedule task | |
} }; | |
my $m := 300000; | |
my $i := 0; | |
my @r; | |
my $b; | |
while $i < $m { | |
exec_delayed('$b'); | |
$i := $i + 1; | |
} | |
# all tasks are set up now, give them time to compute while we sleep | |
nqp::sleep(10); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment