From 34437e34c5a88cde77e7cbdc175528cbe976b0ab Mon Sep 17 00:00:00 2001 From: Rafael Ravedutti <rafaelravedutti@gmail.com> Date: Tue, 29 Mar 2022 23:32:51 +0200 Subject: [PATCH] Add device analysis, Makefile and requirements Signed-off-by: Rafael Ravedutti <rafaelravedutti@gmail.com> --- Makefile | 17 +++++ requirements.txt | 0 src/pairs/analysis/devices.py | 66 +++++++++++++++++++ src/pairs/ir/kernel.py | 97 ++++++++++++++++++++++++++++ src/pairs/ir/module.py | 2 +- src/pairs/transformations/devices.py | 22 +++++++ 6 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 requirements.txt create mode 100644 src/pairs/analysis/devices.py create mode 100644 src/pairs/ir/kernel.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aaf7dbf --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +.PHONY: all build clean lj_ns + +all: build lj_ns clean + @echo "Everything was done!" + +build: + @echo "Building pairs package..." + python3 setup.py build && python3 setup.py install --user + +lj_ns: + @echo "Generating and compiling CPP for Lennard-Jones example..." + python3 examples/lj_func.py + g++ -o lj_ns lj_ns.cpp + +clean: + @echo "Cleaning..." + rm -rf build lj_ns lj_ns.cpp dist pairs.egg-info kernels kernels.pdf diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/pairs/analysis/devices.py b/src/pairs/analysis/devices.py new file mode 100644 index 0000000..94d13ba --- /dev/null +++ b/src/pairs/analysis/devices.py @@ -0,0 +1,66 @@ +from pairs.ir.visitor import Visitor + + +class FetchKernelReferences(Visitor): + def __init__(self, ast): + super().__init__(ast) + self.kernel_stack = [] + self.kernel_decls = {} + self.kernel_used_bin_ops = {} + self.writing = False + + def visit_ArrayAccess(self, ast_node): + # Visit array and save current writing state + self.visit(ast_node.array) + writing_state = self.writing + + # Index elements are read-only + self.writing = False + self.visit([roc for roc in ast_node.children() if roc != ast_node.array]) + self.writing = writing_state + + def visit_Assign(self, ast_node): + self.writing = True + self.visit(ast_node.destinations()) + self.writing = False + self.visit(ast_node.sources()) + + def visit_Kernel(self, ast_node): + kernel_id = ast_node.kernel_id + self.kernel_decls[kernel_id] = [] + self.kernel_used_bin_ops[kernel_id] = [] + self.kernel_stack.append(ast_node) + self.visit_children(ast_node) + self.kernel_stack.pop() + ast_node.add_bin_op([b for b in self.kernel_used_bin_ops[kernel_id] if b not in self.kernel_decls[kernel_id]]) + + def visit_PropertyAccess(self, ast_node): + # Visit property and save current writing state + self.visit(ast_node.prop) + writing_state = self.writing + + # Index elements are read-only + self.writing = False + self.visit([roc for roc in ast_node.children() if roc != ast_node.prop]) + self.writing = writing_state + + def visit_Decl(self, ast_node): + if isinstance(ast_node.elem, BinOp): + for k in self.kernel_stack: + self.kernel_decls[k.kernel_id].append(ast_node) + + def visit_BinOp(self, ast_node): + for k in self.kernel_stack: + self.kernel_used_bin_ops[k.kernel_id].append(ast_node) + + def visit_Array(self, ast_node): + for k in self.kernel_stack: + k.add_array(ast_node, self.writing) + + def visit_Property(self, ast_node): + for k in self.kernel_stack: + k.add_property(ast_node, self.writing) + + def visit_Var(self, ast_node): + for k in self.kernel_stack: + k.add_variable(ast_node, self.writing) diff --git a/src/pairs/ir/kernel.py b/src/pairs/ir/kernel.py new file mode 100644 index 0000000..8f7770c --- /dev/null +++ b/src/pairs/ir/kernel.py @@ -0,0 +1,97 @@ +from pairs.ir.arrays import Array +from pairs.ir.ast_node import ASTNode +from pairs.ir.properties import Property +from pairs.ir.variables import Var + + +class Kernel(ASTNode): + last_kernel = 0 + + def __init__(self, sim, name=None, block=None): + super().__init__(sim) + self._id = Kernel.last_kernel + self._name = name if name is not None else "kernel" + str(Kernel.last_kernel) + self._variables = {} + self._arrays = {} + self._properties = {} + self._bin_ops = [] + self._block = block + sim.add_kernel(self) + Kernel.last_kernel += 1 + + @property + def kernel_id(self): + return self._id + + @property + def name(self): + return self._name + + @property + def block(self): + return self._block + + def variables(self): + return self._variables + + def read_only_variables(self): + return [v for v in self._variables if 'w' not in self._variables[v]] + + def write_variables(self): + return [v for v in self._variables if 'w' in self._variables[v]] + + def arrays(self): + return self._arrays + + def properties(self): + return self._properties + + def properties_to_synchronize(self): + return {p for p in self._properties if self._properties[p][0] == 'r'} + + def write_properties(self): + return {p for p in self._properties if 'w' in self._properties[p]} + + def add_array(self, array, write=False): + array_list = array if isinstance(array, list) else [array] + character = 'w' if write else 'r' + for a in array_list: + assert isinstance(a, Array), "Kernel.add_array(): given element is not of type Array!" + self._arrays[a] = character if a not in self._arrays else self._arrays[a] + character + + def add_variable(self, variable, write=False): + variable_list = variable if isinstance(variable, list) else [variable] + character = 'w' if write else 'r' + for v in variable_list: + assert isinstance(v, Var), "Kernel.add_variable(): given element is not of type Var!" + self._variables[v] = character if v not in self._variables else self._variables[v] + character + + def add_property(self, prop, write=False): + prop_list = prop if isinstance(prop, list) else [prop] + character = 'w' if write else 'r' + for p in prop_list: + assert isinstance(p, Property), "Kernel.add_property(): given element is not of type Property!" + self._properties[p] = character if p not in self._properties else self._properties[p] + character + + def add_bin_op(self, bin_op): + bin_op_list = bin_op if isinstance(bin_op, list) else [bin_op] + for b in bin_op_list: + assert isinstance(b, BinOp), "Kernel.add_bin_op(): given element is not of type BinOp!" + self._bin_ops.append(b) + + def children(self): + return [self._block] + + +class KernelLaunch(ASTNode): + def __init__(self, sim, kernel, iterator, range_min, range_max): + assert isinstance(module, Kernel), "KernelLaunch(): given parameter is not of type Kernel!" + super().__init__(sim) + self._kernel = kernel + self._iterator = iterator + self._range_min = range_min + self._range_max = range_max + + @property + def kernel(self): + return self._kernel diff --git a/src/pairs/ir/module.py b/src/pairs/ir/module.py index d8ffcaf..7353ddd 100644 --- a/src/pairs/ir/module.py +++ b/src/pairs/ir/module.py @@ -9,7 +9,7 @@ class Module(ASTNode): def __init__(self, sim, name=None, block=None, resizes_to_check={}, check_properties_resize=False, run_on_device=False): super().__init__(sim) - self._name = name if name is not None else "module_" + str(Module.last_module) + self._name = name if name is not None else "module" + str(Module.last_module) self._variables = {} self._arrays = {} self._properties = {} diff --git a/src/pairs/transformations/devices.py b/src/pairs/transformations/devices.py index 5305081..1a9a037 100644 --- a/src/pairs/transformations/devices.py +++ b/src/pairs/transformations/devices.py @@ -62,3 +62,25 @@ class AddDeviceCopies(Mutator): ast_node.stmts = new_stmts return ast_node + + +class AddDeviceKernels(Mutator): + def __init__(self, ast): + super().__init__(ast) + + def mutate_Module(self, ast_node): + ast_node._block = self.mutate(ast_node._block) + + if ast_node.run_on_device: + new_stmts = [] + kernel_id = 0 + for s in ast_node._block.stmts: + if s is not None: + if isinstance(s, For) and (not isinstance(s.min, Lit) or not isinstance(s.max, Lit)): + kernel = Kernel(ast_node.sim, f"{ast_node.name}_kernel{kernel_id}", s.block) + new_stmts.append(KernelLaunch(ast_node.sim, kernel, s.iterator, s.min, s.max)) + kernel_id += 1 + else: + new_stmts.append(s) + + return ast_node -- GitLab