Skip to content

Instantly share code, notes, and snippets.

@FROGGS
Created July 31, 2013 23:18
Show Gist options
  • Select an option

  • Save FROGGS/6127100 to your computer and use it in GitHub Desktop.

Select an option

Save FROGGS/6127100 to your computer and use it in GitHub Desktop.
= Call it as: nqp add-i-mt. = It computes the sum of the two input RPMCAs (line 80/81), and returns the array containing the sums.
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 < 100_000;
$ops.push_pirop("push array_b, " ~ ($b := $b + 1)) while $b < 100_000;
$ops.push_pirop("offset = new ['Integer']");
$ops.push_pirop("offset = 0");
$ops.push_pirop("end = new ['Integer']");
$ops.push_pirop("end = 89999");
$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");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment