def filter(self, ast): """ Find the declaration of the """ id_node = None if self.func_call.name.name in self.ignore_names: raise IgnoreMutationException('This function is already implemented on CUDA') try: # ast.show() # from Tools.Debug import DotDebugTool # DotDebugTool().apply(self.func_call) decl = decl_of_id(self.func_call.name, ast) if hasattr(decl, 'storage') and 'extern' in decl.storage: # print "********************" # print dir(decl) # decl.show() # print "********************" print " *** Cannot use external declarations inside kernel *** " print " Decl : " + decl.name raise FilterError("Cannot use external declarations inside kernel") af = FuncDeclOfNameFilter(name = self.func_call.name) id_node = af.apply(ast) # print " Declaration " + str(self.func_call.name) + " is " + str(id_node) # print " Definition " + str(id_node.parent.parent) except NodeNotFound: print " *** Node not found *** " return None # if isinstance(id_node.parent, c_ast.Decl): if isinstance(id_node.parent.parent, c_ast.FileAST): for elem in id_node.parent.parent.ext: if isinstance(elem, c_ast.FuncDef) and elem.decl.name == self.func_call.name: return elem raise NodeNotFound(id_node) else: return id_node.parent.parent
def _get_dict_from_clauses(self, clauses, ast, init=None): """ Return a dict of clauses from a list of OmpClause objects Example: [OmpClause('REDUCTION', ...), OmpClause('PRIVATE', ...)] will return: {'REDUCTION' : [....] , 'PRIVATE' : [...]} :return: dict with clauses """ clause_names = ["SHARED", "PRIVATE", "NOWAIT", "REDUCTION", "COPY_IN", "COPY_OUT"] clause_dict = {} if not init: clause_dict = self._clauses # Note: Each identifiers is a ParamList for elem in clauses: if not clause_dict.has_key(elem.name): clause_dict[elem.name] = [] if elem.name in ["SHARED", "PRIVATE", "REDUCTION", "COPY_IN", "COPY_OUT"]: for id in elem.identifiers.params: decl = decl_of_id(id, ast) if not decl: raise AbortMutationException( " Declaration of " + id.name + " in " + elem.name + " clause could not be found " ) # If a declaration with the same name is already stored, pass. Otherwise, append it to the list for stored_decl in clause_dict[elem.name]: if decl.name == stored_decl.name: break else: clause_dict[elem.name].append(decl) elif elem.name == "NOWAIT": clause_dict[elem.name] = True for name in clause_names: if not clause_dict.has_key(name): clause_dict[name] = [] if not init: self._clauses = clause_dict return clause_dict
def mutatorFunction(self, ast, ompParallel_node): """ CUDA mutator, writes memory transfer operations for a parallel region """ from Backends.Cuda.Mutators.CM_llcNestedFor import CM_llcNestedFor from Backends.Cuda.Mutators.CM_OmpFor import CM_OmpFor threadprivate = [] for elem in OmpThreadPrivateFilter().dfs_iter(ast): threadprivate.extend([decl_of_id(it, ast) for it in elem.identifiers.params]) # print " Threadprivate : " + str(threadprivate) clause_dict = self._get_dict_from_clauses(ompParallel_node.clauses, ast) shared_params = clause_dict['SHARED'] modified_shared_vars = clause_dict['COPY_OUT'] copyin_shared_vars = clause_dict['COPY_IN'] # If no copy clauses specified, default to shared params if len(copyin_shared_vars) == 0 and len(modified_shared_vars) == 0: modified_shared_vars = shared_params copyin_shared_vars = shared_params private_params = clause_dict['PRIVATE'] nowait = clause_dict.has_key('NOWAIT') # If the parallel statement have declarations, they are private to the thread, so, we need to put them as params print " Parallel : " + str(ompParallel_node) if ompParallel_node.stmt.decls: private_params += ompParallel_node.stmt.decls private_params.extend(threadprivate) # Loops inside parallel region (wired for now) CM_llcNestedFor(clause_dict, kernel_name = self.kernel_prefix + "_nestedLoopKernel").apply_all(ompParallel_node, ast) CM_OmpFor(clause_dict, kernel_name = self.kernel_prefix + "_loopKernel").apply_all(ompParallel_node, ast) ##################### Statement for cuda cuda_stmts = c_ast.Compound(stmts = [], decls = []); ##################### Cuda parameters on host ##################### Declarations declarations_subtree = self.buildParallelDeclarations(shared_node_list = copyin_shared_vars, ast = ast) InsertTool(subtree = declarations_subtree, position = "begin").apply(cuda_stmts, 'decls') # Initialization # initialization_subtree = self.buildInitialization(shared_vars = shared_params, ast = ast) InsertTool(subtree = self._parallel.stmt, position = "begin").apply(cuda_stmts, 'stmts') # InsertTool(subtree = initialization_subtree, position = "begin").apply(cuda_stmts, 'stmts') # Retrieve data retrieve_subtree = self.buildRetrieve(reduction_vars = [], modified_shared_vars = modified_shared_vars, ast = ast, shared_vars = copyin_shared_vars) InsertTool(subtree = retrieve_subtree, position = "end").apply(cuda_stmts, 'stmts') ##################### Support subtree ### Support has been moved to an external include file # support_subtree = self.buildSupport() # InsertTool(subtree = c_ast.Compound(stmts = support_subtree.stmts, decls = None), position = "end").apply(ast, 'ext') # InsertTool(subtree = c_ast.Compound(decls = support_subtree.decls, stmts = None), position = "begin").apply(ast, 'ext') print " *** You must include reduction_snippets.h after translation *** " ##################### Loop substitution # Replace the entire pragma by a CompoundStatement with all the new statements # Note: The parent of Parallel is always a Pragma node ReplaceTool(new_node = cuda_stmts, old_node = self._parallel.parent).apply(self._parallel.parent.parent, 'stmts')