def get_call_template(self, args, kws): """ Get a typing.ConcreteTemplate for this dispatcher and the given *args* and *kws* types. This allows to resolve the return type. """ # Fold keyword arguments and resolve default values def normal_handler(index, param, value): return value def default_handler(index, param, default): return self.typeof_pyval(default) def stararg_handler(index, param, values): return types.Tuple(values) args = fold_arguments(self._pysig, args, kws, normal_handler, default_handler, stararg_handler) kws = {} # Ensure an overload is available, but avoid compiler re-entrance if self._can_compile and not self.is_compiling: self.compile(tuple(args)) # Create function type for typing func_name = self.py_func.__name__ name = "CallTemplate({0})".format(func_name) # The `key` isn't really used except for diagnosis here, # so avoid keeping a reference to `cfunc`. call_template = typing.make_concrete_template( name, key=func_name, signatures=self.nopython_signatures) return call_template, args, kws
def make_function_type(cffi_func): cffi_type = ffi.typeof(cffi_func) signature = map_type(cffi_type) cases = [signature] template = typing.make_concrete_template("CFFIFuncPtr", cffi_func, cases) result = types.FunctionPointer(template, get_pointer(cffi_func)) return result
def get_call_template(self, args, kws): """ Get a typing.ConcreteTemplate for this dispatcher and the given *args* and *kws* types. This allows to resolve the return type. A (template, pysig, args, kws) tuple is returned. """ # XXX how about a dispatcher template class automating the # following? # Fold keyword arguments and resolve default values pysig, args = self._compiler.fold_argument_types(args, kws) kws = {} # Ensure an overload is available if self._can_compile: self.compile(tuple(args)) # Create function type for typing func_name = self.py_func.__name__ name = "CallTemplate({0})".format(func_name) # The `key` isn't really used except for diagnosis here, # so avoid keeping a reference to `cfunc`. call_template = typing.make_concrete_template( name, key=func_name, signatures=self.nopython_signatures) return call_template, pysig, args, kws
def get_call_template(self, args, kws): """ Get a typing.ConcreteTemplate for this dispatcher and the given *args* and *kws*. This allows to resolve the return type. """ # Fold keyword arguments if kws: ba = self._pysig.bind(*args, **kws) if ba.kwargs: # There's a remaining keyword argument, e.g. if omitting # some argument with a default value before it. raise NotImplementedError("unhandled keyword argument: %s" % list(ba.kwargs)) args = ba.args kws = {} # Ensure an overload is available, but avoid compiler re-entrance if self._can_compile and not self.is_compiling: self.compile(tuple(args)) # Create function type for typing func_name = self.py_func.__name__ name = "CallTemplate({0})".format(func_name) # The `key` isn't really used except for diagnosis here, # so avoid keeping a reference to `cfunc`. call_template = typing.make_concrete_template( name, key=func_name, signatures=self.nopython_signatures) return call_template, args, kws
def get_call_template(self, args, kws): """ Get a typing.ConcreteTemplate for this dispatcher and the given *args* and *kws*. This allows to resolve the return type. """ # Fold keyword arguments if kws: ba = self._pysig.bind(*args, **kws) if ba.kwargs: # There's a remaining keyword argument, e.g. if omitting # some argument with a default value before it. raise NotImplementedError("unhandled keyword argument: %s" % list(ba.kwargs)) args = ba.args kws = {} # Ensure an overload is available, but avoid compiler re-entrance if self._can_compile and not self.is_compiling: self.compile(tuple(args)) # Create function type for typing func_name = self.py_func.__name__ name = "CallTemplate({0})".format(func_name) # The `key` isn't really used except for diagnosis here, # so avoid keeping a reference to `cfunc`. call_template = typing.make_concrete_template(name, key=func_name, signatures=self.nopython_signatures) return call_template, args, kws
def test_scalar(self): flags = Flags() # Compile the inner function global cnd_jitted cr1 = compile_isolated(cnd, (types.float64,)) cnd_jitted = cr1.entry_point # Manually type the compiled function for calling into tyctx = cr1.typing_context ctx = cr1.target_context signature = typing.make_concrete_template("cnd_jitted", cnd_jitted, [cr1.signature]) tyctx.insert_user_function(cnd_jitted, signature) # Compile the outer function array = types.Array(types.float64, 1, 'C') argtys = (array,) * 5 + (types.float64, types.float64) cr2 = compile_extra(tyctx, ctx, blackscholes_scalar_jitted, args=argtys, return_type=None, flags=flags, locals={}) jitted_bs = cr2.entry_point OPT_N = 400 iterations = 10 callResultGold = np.zeros(OPT_N) putResultGold = np.zeros(OPT_N) callResultNumba = np.zeros(OPT_N) putResultNumba = np.zeros(OPT_N) stockPrice = randfloat(self.random.random_sample(OPT_N), 5.0, 30.0) optionStrike = randfloat(self.random.random_sample(OPT_N), 1.0, 100.0) optionYears = randfloat(self.random.random_sample(OPT_N), 0.25, 10.0) args = stockPrice, optionStrike, optionYears, RISKFREE, VOLATILITY ts = timer() for i in range(iterations): blackscholes_scalar(callResultGold, putResultGold, *args) te = timer() pytime = te - ts ts = timer() for i in range(iterations): jitted_bs(callResultNumba, putResultNumba, *args) te = timer() jittime = te - ts print("Python", pytime) print("Numba", jittime) print("Speedup: %s" % (pytime / jittime)) delta = np.abs(callResultGold - callResultNumba) L1norm = delta.sum() / np.abs(callResultGold).sum() print("L1 norm: %E" % L1norm) print("Max absolute error: %E" % delta.max()) self.assertAlmostEqual(delta.max(), 0)
def make_function_type(cfnptr): cargs = [convert_ctypes(a) for a in cfnptr.argtypes] cret = convert_ctypes(cfnptr.restype) cases = [typing.signature(cret, *cargs)] template = typing.make_concrete_template("CFuncPtr", cfnptr, cases) pointer = ctypes.cast(cfnptr, ctypes.c_void_p).value return types.FunctionPointer(template, pointer)
def __init__(self, symbol, cstring): """Parse C function declaration/signature""" self.symbol = symbol parser = cffi.cparser.Parser() rft = parser.parse_type(cstring) # "RawFunctionType" self.restype = type_map[rft.result.build_backend_type(ffi, None)] self.argtypes = [type_map[arg.build_backend_type(ffi, None)] for arg in rft.args] signature = typing.signature(self.restype, *self.argtypes) cases = [signature] template = typing.make_concrete_template('ExternCFunction', self.symbol, cases) super(ExternCFunction, self).__init__(template)
def __init__(self, symbol, cstring): """Parse C function declaration/signature""" self.symbol = symbol parser = cffi.cparser.Parser() rft = parser.parse_type(cstring) # "RawFunctionType" self.restype = type_map[rft.result.build_backend_type(ffi, None)] self.argtypes = [ type_map[arg.build_backend_type(ffi, None)] for arg in rft.args ] signature = typing.signature(self.restype, *self.argtypes) cases = [signature] template = typing.make_concrete_template('ExternCFunction', self.symbol, cases) super(ExternCFunction, self).__init__(template)
def test_scalar(self): flags = Flags() # Compile the inner function global cnd_jitted cr1 = compile_isolated(cnd, (types.float64, )) cnd_jitted = cr1.entry_point # Manually type the compiled function for calling into tyctx = cr1.typing_context ctx = cr1.target_context signature = typing.make_concrete_template("cnd_jitted", cnd_jitted, [cr1.signature]) tyctx.insert_user_function(cnd_jitted, signature) # Compile the outer function array = types.Array(types.float64, 1, 'C') argtys = (array, ) * 5 + (types.float64, types.float64) cr2 = compile_extra(tyctx, ctx, blackscholes_scalar_jitted, args=argtys, return_type=None, flags=flags, locals={}) jitted_bs = cr2.entry_point OPT_N = 400 iterations = 10 callResultGold = np.zeros(OPT_N) putResultGold = np.zeros(OPT_N) callResultNumba = np.zeros(OPT_N) putResultNumba = np.zeros(OPT_N) stockPrice = randfloat(self.random.random_sample(OPT_N), 5.0, 30.0) optionStrike = randfloat(self.random.random_sample(OPT_N), 1.0, 100.0) optionYears = randfloat(self.random.random_sample(OPT_N), 0.25, 10.0) args = stockPrice, optionStrike, optionYears, RISKFREE, VOLATILITY blackscholes_scalar(callResultGold, putResultGold, *args) jitted_bs(callResultNumba, putResultNumba, *args) delta = np.abs(callResultGold - callResultNumba) L1norm = delta.sum() / np.abs(callResultGold).sum() print("L1 norm: %E" % L1norm) print("Max absolute error: %E" % delta.max()) self.assertAlmostEqual(delta.max(), 0)
def get_call_template(self, args, kws): """ Get a typing.ConcreteTemplate for this dispatcher and the given *args* and *kws*. This allows to resolve the return type. """ if kws: raise TypeError("kwargs not supported") # Ensure an overload is available, but avoid compiler re-entrance if self._can_compile and not self.is_compiling: self.compile(tuple(args)) # Create function type for typing func_name = self.py_func.__name__ name = "CallTemplate({0})".format(func_name) # The `key` isn't really used except for diagnosis here, # so avoid keeping a reference to `cfunc`. call_template = typing.make_concrete_template( name, key=func_name, signatures=self.nopython_signatures) return call_template
def get_call_template(self, args, kws): """ Get a typing.ConcreteTemplate for this dispatcher and the given *args* and *kws* types. This enables the resolving of the return type. A (template, pysig, args, kws) tuple is returned. """ # Ensure an overload is available if self._can_compile: self.compile(tuple(args)) pysig = None # Create function type for typing func_name = self.py_func.__name__ name = "CallTemplate({0})".format(func_name) # The `key` isn't really used except for diagnosis here, # so avoid keeping a reference to `cfunc`. call_template = typing.make_concrete_template( name, key=func_name, signatures=self.nopython_signatures) return call_template, pysig, args, kws
def add_overload(self, cres): args = tuple(cres.signature.args) sig = [a._code for a in args] self._insert(sig, cres.entry_point, cres.objectmode, cres.interpmode) self.overloads[args] = cres.entry_point self._compileinfos[args] = cres # Add native function for correct typing the code generation target = cres.target_context cfunc = cres.entry_point if cfunc in target.native_funcs: target.dynamic_map_function(cfunc) # Create function type for typing func_name = cres.fndesc.mangled_name name = "CallTemplate(%s)" % cres.fndesc.mangled_name # The `key` isn't really used except for diagnosis here, # so avoid keeping a reference to `cfunc`. call_template = typing.make_concrete_template( name, key=func_name, signatures=[cres.signature]) self._function_types[args] = call_template
def add_overload(self, cres): args = tuple(cres.signature.args) sig = [a._code for a in args] self._insert(sig, cres.entry_point, cres.objectmode) self.overloads[args] = cres.entry_point self._compileinfos[args] = cres # Add native function for correct typing the code generation target = cres.target_context cfunc = cres.entry_point if cfunc in target.native_funcs: target.dynamic_map_function(cfunc) # Create function type for typing func_name = cres.fndesc.mangled_name name = "CallTemplate(%s)" % cres.fndesc.mangled_name # The `key` isn't really used except for diagnosis here, # so avoid keeping a reference to `cfunc`. call_template = typing.make_concrete_template( name, key=func_name, signatures=[cres.signature]) self._function_types[args] = call_template
def get_call_template(self, args, kws): """ Get a typing.ConcreteTemplate for this dispatcher and the given *args* and *kws* types. This enables the resolving of the return type. A (template, pysig, args, kws) tuple is returned. """ assert not kws self._legalize_arg_types(args) # Coerce to object mode args = [types.ffi_forced_object] * len(args) if self._can_compile: self.compile(tuple(args)) signatures = [typing.signature(self.output_types, *args)] pysig = None func_name = self.py_func.__name__ name = "CallTemplate({0})".format(func_name) call_template = typing.make_concrete_template( name, key=func_name, signatures=signatures) return call_template, pysig, args, kws