def field_value(closure_arg): obj = type_conv.from_python(closure_arg) parakeet_type = type_conv.typeof(closure_arg) if isinstance(parakeet_type, StructT): return ctypes.pointer(obj) else: return obj
def get_par_args_repr(nonlocals, nonlocal_types, args, arg_types, return_t): # Create args struct type fields = [] arg_counter = 0 for arg_type in nonlocal_types: fields.append((("arg%d" % arg_counter), arg_type)) arg_counter += 1 for arg_type in arg_types: fields.append((("arg%d" % arg_counter), arg_type)) arg_counter += 1 fields.append(("output", return_t)) class ParArgsType(core_types.StructT): _fields_ = fields def __hash__(self): return hash(tuple(fields)) def __eq__(self, other): return isinstance(other, ParArgsType) args_repr = ParArgsType() c_args = args_repr.ctypes_repr() arg_counter = 0 for arg in nonlocals: obj = type_conv.from_python(arg) field_name = "arg%d" % arg_counter t = type_conv.typeof(arg) if isinstance(t, core_types.StructT): setattr(c_args, field_name, ctypes.pointer(obj)) else: setattr(c_args, field_name, obj) arg_counter += 1 for arg in args: obj = type_conv.from_python(arg) field_name = "arg%d" % arg_counter t = type_conv.typeof(arg) if isinstance(t, core_types.StructT): setattr(c_args, field_name, ctypes.pointer(obj)) else: setattr(c_args, field_name, obj) arg_counter += 1 return args_repr, c_args
def from_python(self, python_tuple, _keep_forever = []): # _keep_forever.append(python_tuple) converted_elts = [] for elt in python_tuple: parakeet_type = type_conv.typeof(elt) c_elt = parakeet_type.from_python(elt) if isinstance(parakeet_type, StructT): c_elt = ctypes.pointer(c_elt) converted_elts.append(c_elt) return self.ctypes_repr(*converted_elts)
def from_python(self, python_tuple, _keep_forever=[]): # _keep_forever.append(python_tuple) converted_elts = [] for elt in python_tuple: parakeet_type = type_conv.typeof(elt) c_elt = parakeet_type.from_python(elt) if isinstance(parakeet_type, StructT): c_elt = ctypes.pointer(c_elt) converted_elts.append(c_elt) return self.ctypes_repr(*converted_elts)
def from_python(python_value): if isinstance(python_value, np.ndarray): elt_size = python_value.dtype.itemsize strides = [] for s in python_value.strides: strides.append(specialization_const(s/elt_size)) return abstract_array(strides) elif isinstance(python_value, tuple): return abstract_tuple(from_python_list(python_value)) else: parakeet_type = type_conv.typeof(python_value) parakeet_value = type_conv.from_python(python_value) return from_internal_repr(parakeet_type, parakeet_value)
def par_allpairs(fn, x, y, **kwds): axis = kwds.get('axis', 0) assert axis == 0, "Other axes not yet implemented" untyped, closure_t, nonlocals, args, arg_types = \ prepare_adverb_args(fn, [x, y], kwds) xtype, ytype = arg_types elt_result_t, typed_fn = \ type_inference.specialize_AllPairs(closure_t, xtype, ytype) # Actually, for now, just split the first one. Otherwise we'd have to carve # the output along axis = 1 and I don't feel like figuring that out. num_iters = len(args.positional[0]) dont_slice_position = 1 + len(nonlocals) nonlocal_types = [type_conv.typeof(arg) for arg in nonlocals] args_repr, c_args = get_par_args_repr(nonlocals, nonlocal_types, args, arg_types, elt_result_t) # TODO: Use axes other than 0 outer_shape = (len(x), len(y)) try: combined_args = args.prepend_positional(nonlocals) linearized_args = \ untyped.args.linearize_without_defaults(combined_args, iter) inner_shape = shape_eval.result_shape(typed_fn, linearized_args) output_shape = outer_shape + inner_shape dtype = array_type.elt_type(typed_fn.return_type).dtype output = np.zeros(shape = output_shape, dtype = dtype) except: single_iter_rslt = run_function.run(fn, x[0], y[0]) output = allocate_output(outer_shape, single_iter_rslt, c_args, elt_result_t) output_obj = type_conv.from_python(output) gv_output = ctypes.pointer(output_obj) c_args.output = gv_output wf = gen_par_work_function(adverbs.AllPairs, untyped, nonlocals, nonlocal_types, args_repr, arg_types, dont_slice_position) exec_in_parallel(wf, args_repr, c_args, num_iters) return output
def prepare_adverb_args(python_fn, args, kwargs): """ Fetch the function's nonlocals and return an ActualArgs object of both the arg values and their types """ closure_t = type_conv.typeof(python_fn) assert isinstance(closure_t, closure_type.ClosureT) if isinstance(closure_t.fn, str): untyped = syntax.Fn.registry[closure_t.fn] else: untyped = closure_t.fn nonlocals = list(untyped.python_nonlocals()) adverb_arg_values = ActualArgs(args, kwargs) # get types of all inputs adverb_arg_types = adverb_arg_values.transform(type_conv.typeof) return untyped, closure_t, nonlocals, adverb_arg_values, adverb_arg_types
def keyword_fn(local_name, value): unbound_keywords.append(local_name) return type_conv.typeof(value)
def expr_Const(): return typed_ast.Const(expr.value, type_conv.typeof(expr.value))
def keyword_fn(_, v): return type_conv.typeof(v)
def transform_Const(self, expr): return syntax.Const(expr.value, type_conv.typeof(expr.value))
def typeof_slice(s): start_type = type_conv.typeof(s.start) stop_type = type_conv.typeof(s.stop) step_type = type_conv.typeof(s.step) return make_slice_type(start_type, stop_type, step_type)
def par_each(fn, *args, **kwds): if 'axis' in kwds: axis = kwds['axis'] del kwds['axis'] else: axis = 0 assert axis == 0, "Map over axis %d not yet supported" % axis untyped, closure_t, nonlocals, args, arg_types = \ prepare_adverb_args(fn, args, kwds) elt_result_t, typed_fn = type_inference.specialize_Map(closure_t, arg_types) # TODO: Why do we have to do this? Shouldn't we just check that the length # of each arg along the axis dimension is the same, and then use that # common length? I.e., why can't adverbs have args of different ranks # so long as they share the same length in the axis dimension? #r = adverb_helpers.max_rank(arg_types) #for (arg, t) in zip(args, arg_types): # if t.rank == r: # max_arg = arg # break #num_iters = max_arg.shape[axis] num_iters = args.positional[0].shape[axis] nonlocal_types = [type_conv.typeof(arg) for arg in nonlocals] args_repr, c_args = get_par_args_repr(nonlocals, nonlocal_types, args, arg_types, elt_result_t) outer_shape = (num_iters,) try: # mysterious segfaults likely related to a mistake in shape inference but # seem to get fixed by defaulting to actually running the first iter combined_args = args.prepend_positional(nonlocals) linearized_args = \ untyped.args.linearize_without_defaults(combined_args, iter) inner_shape = shape_eval.result_shape(typed_fn, linearized_args) print inner_shape output_shape = outer_shape + inner_shape dtype = array_type.elt_type(elt_result_t).dtype output = np.zeros(shape = output_shape, dtype = dtype) output_obj = type_conv.from_python(output) gv_output = ctypes.pointer(output_obj) setattr(c_args, "output", gv_output) except: print "Warning: shape inference failed for parallel each" raise single_iter_rslt = \ run_function.run(fn, *[arg[0] for arg in args.positional]) output = allocate_output(outer_shape, single_iter_rslt, c_args, elt_result_t) wf = gen_par_work_function(adverbs.Map, untyped, nonlocals, nonlocal_types, args_repr, arg_types, []) exec_in_parallel(wf, args_repr, c_args, num_iters) return output