SMP/OpenMP
SMP Tagged Code Objects
Parallel Loop == smp_for
# spiral-core\namespaces\spiral\paradigms\smp\code.gi
Class(smp_loop, loop_base, rec(
__call__ := meth(self, nthreads, tidvar, tidexp,
loopvar, range, cmd)
local result;
range := toRange(range);
loopvar.setRange(range);
loopvar.isLoopIndex := true;
return WithBases(self, rec(
operations := CmdOps,
nthreads := nthreads,
cmd := cmd,
var := loopvar,
tidvar := Checked(IsLoc(tidvar), tidvar),
tidexp := toExpArg(tidexp),
range := range));
end,
print := (self, i, is) >> Print(self.name,"(",self.nthreads,", ",
self.tidvar, ", ", self.tidexp, ", ", self.var, ", ",
self.range, ",\n", Blanks(i+is),
self.cmd.print(i+is, is),
Print("\n", Blanks(i), ")")),
));
SMP Code Objects and Code Generator
Thread ID
# spiral-core\namespaces\spiral\paradigms\smp\sigmaspl.gi
Class(threadId, Exp, rec(computeType := self >> TInt));
Barrier
Class(barrier, call, rec(visitAs := call));
SMP Codegenerator
Class(SMPCodegenMixin, Codegen, rec(
SMPBarrier := (self, o, y, x, opts) >> chain(
self(o.child(1), y, x, opts),
barrier(o.nthreads, o.tid, "&GLOBAL_BARRIER")),
SMPSum := (self, o, y, x, opts) >> let(
outer_tid := When(IsBound(opts._tid), opts._tid, 0),
outer_num_thr := When(IsBound(opts._tid), opts._tid.range, 1),
tid := var.fresh("tid", TInt, o.nthreads * outer_num_thr),
smp_loop(o.nthreads, tid, (outer_tid * outer_num_thr) + o.tid,
o.var, o.domain,
self(o.child(1), y, x,
CopyFields(opts, rec(_tid := tid))))
)
));
OpenMP Unparser
Parallel For
Definition
# Unparser for #pragma omp parallel for
Class(OpenMP_Unparser, OpenMP_UnparseMixin_ParFor, CUnparserProg);
Mixin
# spiral-core\namespaces\spiral\paradigms\smp\unparsed.gi
Class(OpenMP_UnparseMixin_ParFor, SMP_UnparseMixin, rec(
includes := ["<omp.h>"],
threadId := (self,o,i,is) >> Print("omp_get_thread_num()"),
barrier := (self,o,i, is) >>
Print(Blanks(i), "/* SMP barrier */\n"),
smp_loop := (self,o,i,is) >> let(v := o.var,
lo := 0, hi := o.range,
Print(Blanks(i),
"#pragma omp parallel for schedule(static, ",
Int((hi+1)/2),")\n",
Blanks(i), "for(int ", v, " = ", lo, "; ", v,
" < ", hi, "; ", v, "++) {\n",
Blanks(i + is), "int ", o.tidvar, " = ", v, ";\n",
self.opts.unparser(o.cmd,i+is,is),
Blanks(i), "}\n")),
));
Parallel Region
Definition
# Unparser for #pragma omp parallel regions
# namespaces/spiral/libgen/recgt.gi
Class(OpenMP_Unparser, OpenMP_UnparseMixin, CUnparserProg);
Mixin
# spiral-core\namespaces\spiral\paradigms\smp\unparsed.gi
Class(OpenMP_UnparseMixin, SMP_UnparseMixin, rec(
includes := ["<omp.h>"],
smp_fork := (self, o, i, is) >> Print(
Blanks(i), "#pragma omp parallel num_threads(",
o.nthreads, ")\n",
Blanks(i), "{\n",
self(o.cmd, i+is, is),
Blanks(i), "}\n"
),
threadId := (self,o,i,is) >> Print("omp_get_thread_num()"),
barrier := (self,o,i, is) >> Print("#pragma omp barrier\n")
));