Created
July 31, 2013 23:18
-
-
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.
This file contains hidden or 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 < 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