Skip to content

Instantly share code, notes, and snippets.

@FROGGS
Last active December 20, 2015 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FROGGS/0cfae647d28c493df73e to your computer and use it in GitHub Desktop.
Save FROGGS/0cfae647d28c493df73e to your computer and use it in GitHub Desktop.
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
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");
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