def test_overload(self): # Create an overloaded blaze func, populate it with # some ckernel implementations extracted from numpy, # and test some calls on it. d = blaze.overloading.Dispatcher() myfunc = blaze.BlazeFunc(d) def myfunc_dummy(x, y): raise NotImplementedError # overload int32 -> np.add sig = blaze.dshape("A..., int32 -> A..., int32 -> A..., int32") d.add_overload(myfunc_dummy, sig, {}) ckd = _lowlevel.ckernel_deferred_from_ufunc(np.add, (np.int32, np.int32, np.int32), False) myfunc.implement(myfunc_dummy, sig, "ckernel", ckd) # overload int16 -> np.subtract (so we can see the difference) sig = blaze.dshape("A..., int16 -> A..., int16 -> A..., int16") d.add_overload(myfunc_dummy, sig, {}) ckd = _lowlevel.ckernel_deferred_from_ufunc(np.subtract, (np.int16, np.int16, np.int16), False) myfunc.implement(myfunc_dummy, sig, "ckernel", ckd) # int32 overload -> add a = blaze.eval(myfunc(blaze.array([3,4]), blaze.array([1,2]))) self.assertEqual(a.dshape, blaze.dshape('2, int32')) self.assertEqual(nd.as_py(a._data.dynd_arr()), [4, 6]) # int16 overload -> subtract a = blaze.eval(myfunc(blaze.array([3,4], dshape='int16'), blaze.array([1,2], dshape='int16'))) self.assertEqual(a.dshape, blaze.dshape('2, int16')) self.assertEqual(nd.as_py(a._data.dynd_arr()), [2, 2]) # type promotion to int32 a = blaze.eval(myfunc(blaze.array([3,4], dshape='int16'), blaze.array([1,2]))) self.assertEqual(a.dshape, blaze.dshape('2, int32')) self.assertEqual(nd.as_py(a._data.dynd_arr()), [4, 6]) a = blaze.eval(myfunc(blaze.array([3,4]), blaze.array([1,2], dshape='int16'))) self.assertEqual(a.dshape, blaze.dshape('2, int32')) self.assertEqual(nd.as_py(a._data.dynd_arr()), [4, 6]) # type promotion to int16 a = blaze.eval(myfunc(blaze.array([3,4], dshape='int8'), blaze.array([1,2], dshape='int8'))) self.assertEqual(a.dshape, blaze.dshape('2, int16')) self.assertEqual(nd.as_py(a._data.dynd_arr()), [2, 2]) # A little bit of nesting a = blaze.eval(myfunc(myfunc(blaze.array([3,4]), blaze.array([1,2])), blaze.array([2,10]))) self.assertEqual(a.dshape, blaze.dshape('2, int32')) self.assertEqual(nd.as_py(a._data.dynd_arr()), [6, 16]) # More nesting, with conversions a = blaze.eval(myfunc(myfunc(blaze.array([1,2]), blaze.array([-2, 10])), myfunc(blaze.array([1, 5], dshape='int16'), blaze.array(3, dshape='int16')))) self.assertEqual(a.dshape, blaze.dshape('2, int32')) self.assertEqual(nd.as_py(a._data.dynd_arr()), [-3, 14])
def test_overload_different_argcount(self): myfunc = BlazeFunc('test', 'ovld') # Two parameter overload ckd = _lowlevel.ckernel_deferred_from_ufunc(np.add, (np.int32,) * 3, False) myfunc.add_overload("(A... * int32, A... * int32) -> A... * int32", ckd) # One parameter overload ckd = _lowlevel.ckernel_deferred_from_ufunc(np.negative, (np.int32,) * 2, False) myfunc.add_overload("(A... * int16, A... * int16) -> A... * int16", ckd) return myfunc
def test_overload_different_argcount(self): myfunc = ElementwiseBlazeFunc('test', 'ovld') # Two parameter overload ckd = _lowlevel.ckernel_deferred_from_ufunc(np.add, (np.int32,) * 3, False) myfunc.add_overload("(int32, int32) -> int32", ckd) # One parameter overload ckd = _lowlevel.ckernel_deferred_from_ufunc(np.negative, (np.int32,) * 2, False) myfunc.add_overload("(int16, int16) -> int16", ckd) return myfunc
def blazefunc_from_numpy_ufunc(uf, modname, name, acquires_gil): """Converts a NumPy ufunc into a Blaze ufunc. Parameters ---------- uf : NumPy ufunc The ufunc to convert. modname : str The module name to report in the ufunc's name name : str The ufunc's name. acquires_gil : bool True if the kernels in the ufunc need the GIL. TODO: should support a dict {type -> bool} to allow per-kernel control. """ # Get the list of type signatures tplist = _lowlevel.numpy_typetuples_from_ufunc(uf) tplist = _filter_tplist(tplist) siglist = [_make_sig(tp) for tp in tplist] kernlist = [_lowlevel.ckernel_deferred_from_ufunc(uf, tp, acquires_gil) for tp in tplist] # Create the empty blaze function to start bf = ElementwiseBlazeFunc('blaze', name) # TODO: specify elementwise #bf.add_metadata({'elementwise': True}) # Add an overload to the function for each signature for (tp, sig, kern) in zip(tplist, siglist, kernlist): bf.add_overload(sig, kern) return bf
def test_lift_ckernel(self): # First get a ckernel from numpy requiregil = False ckd = _lowlevel.ckernel_deferred_from_ufunc(np.ldexp, (np.float64, np.float64, np.int32), requiregil) self.assertEqual(nd.as_py(ckd.types), [ndt.float64, ndt.float64, ndt.int32]) # Now lift it ckd_lifted = _lowlevel.lift_ckernel_deferred(ckd, ['var * var * float64', 'strided * var * float64', 'strided * 1 * int32']) self.assertEqual(nd.as_py(ckd_lifted.types), [ndt.type(x) for x in ['var * var * float64', 'strided * var * float64', 'strided * 1 * int32']]) # Create some compatible arguments out = nd.empty('var * var * float64') in0 = nd.array([[1, 2, 3], [4, 5], [6], [7,9,10]], type='strided * var * float64') in1 = nd.array([[-1], [10], [100], [-12]], type='strided * 1 * int32') # Instantiate and call the kernel on these arguments ckd_lifted.__call__(out, in0, in1) # Verify that we got the expected result self.assertEqual(nd.as_py(out), [[0.5, 1.0, 1.5], [4096.0, 5120.0], [float(6*2**100)], [0.001708984375, 0.002197265625, 0.00244140625]])
def blazefunc_from_numpy_ufunc(uf, modname, name, acquires_gil): """Converts a NumPy ufunc into a Blaze ufunc. Parameters ---------- uf : NumPy ufunc The ufunc to convert. modname : str The module name to report in the ufunc's name name : str The ufunc's name. acquires_gil : bool True if the kernels in the ufunc need the GIL. TODO: should support a dict {type -> bool} to allow per-kernel control. """ # Get the list of type signatures tplist = _lowlevel.numpy_typetuples_from_ufunc(uf) tplist = _filter_tplist(tplist) siglist = [_make_sig(tp) for tp in tplist] kernlist = [_lowlevel.ckernel_deferred_from_ufunc(uf, tp, acquires_gil) for tp in tplist] # Create the empty blaze function to start blaze_func = function.BlazeFunc() blaze_func.add_metadata({'elementwise': True}) # Add default dummy dispatching for 'python' mode pydispatcher = blaze_func.get_dispatcher('python') # Add dispatching to the kernel for each signature ckdispatcher = blaze_func.get_dispatcher('ckernel') for (tp, sig, kern) in zip(tplist, siglist, kernlist): # The blaze function currently requires matching (do-nothing) # python functions pyfunc = _make_pyfunc(len(tp) - 1, modname, name) datashape.overloading.overload(sig, dispatcher=pydispatcher)(pyfunc) datashape.overloading.overload(sig, dispatcher=ckdispatcher)(kern) return blaze_func
def blazefunc_from_numpy_ufunc(uf, modname, name, acquires_gil): """Converts a NumPy ufunc into a Blaze ufunc. Parameters ---------- uf : NumPy ufunc The ufunc to convert. modname : str The module name to report in the ufunc's name name : str The ufunc's name. acquires_gil : bool True if the kernels in the ufunc need the GIL. TODO: should support a dict {type -> bool} to allow per-kernel control. """ # Get the list of type signatures tplist = _lowlevel.numpy_typetuples_from_ufunc(uf) tplist = _filter_tplist(tplist) siglist = [_make_sig(tp) for tp in tplist] kernlist = [ _lowlevel.ckernel_deferred_from_ufunc(uf, tp, acquires_gil) for tp in tplist ] # Create the empty blaze function to start bf = ElementwiseBlazeFunc('blaze', name) # TODO: specify elementwise #bf.add_metadata({'elementwise': True}) # Add an overload to the function for each signature for (tp, sig, kern) in zip(tplist, siglist, kernlist): bf.add_overload(sig, kern) return bf
def create_overloaded_add(): # Create an overloaded blaze func, populate it with # some ckernel implementations extracted from numpy, # and test some calls on it. myfunc = BlazeFunc('test', 'myfunc') # overload int32 -> np.add ckd = _lowlevel.ckernel_deferred_from_ufunc(np.add, (np.int32, np.int32, np.int32), False) myfunc.add_overload("(A... * int32, A... * int32) -> A... * int32", ckd) # overload int16 -> np.subtract (so we can see the difference) ckd = _lowlevel.ckernel_deferred_from_ufunc(np.subtract, (np.int16, np.int16, np.int16), False) myfunc.add_overload("(A... * int16, A... * int16) -> A... * int16", ckd) return myfunc
def create_overloaded_add(): # Create an overloaded blaze func, populate it with # some ckernel implementations extracted from numpy, # and test some calls on it. myfunc = ElementwiseBlazeFunc('test', 'myfunc') # overload int32 -> np.add ckd = _lowlevel.ckernel_deferred_from_ufunc(np.add, (np.int32, np.int32, np.int32), False) myfunc.add_overload("(int32, int32) -> int32", ckd) # overload int16 -> np.subtract (so we can see the difference) ckd = _lowlevel.ckernel_deferred_from_ufunc(np.subtract, (np.int16, np.int16, np.int16), False) myfunc.add_overload("(int16, int16) -> int16", ckd) return myfunc
def create_overloaded_add(): # Create an overloaded blaze func, populate it with # some ckernel implementations extracted from numpy, # and test some calls on it. #d = blaze.overloading.Dispatcher() @function('A -> A -> A') def myfunc(x, y): raise NotImplementedError # overload int32 -> np.add ckd = _lowlevel.ckernel_deferred_from_ufunc(np.add, (np.int32, np.int32, np.int32), False) kernel(myfunc, "ckernel", ckd, "A..., int32 -> A..., int32 -> A..., int32") # overload int16 -> np.subtract (so we can see the difference) ckd = _lowlevel.ckernel_deferred_from_ufunc(np.subtract, (np.int16, np.int16, np.int16), False) kernel(myfunc, "ckernel", ckd, "A..., int16 -> A..., int16 -> A..., int16") return myfunc
def test_sum_2d_axisall(self): # Use the numpy add ufunc for this lifting test ckd = _lowlevel.ckernel_deferred_from_ufunc(np.add, (np.int32, np.int32, np.int32), False) in0 = nd.array([[3, 12, -5], [10, 2, 3]]) # Simple lift sum = _lowlevel.lift_reduction_ckernel_deferred(ckd, 'strided * strided * int32', commutative=True, associative=True) out = nd.empty(ndt.int32) sum.__call__(out, in0) self.assertEqual(nd.as_py(out), 25)
def test_sum_1d(self): # Use the numpy add ufunc for this lifting test ckd = _lowlevel.ckernel_deferred_from_ufunc(np.add, (np.int32, np.int32, np.int32), False) in0 = nd.array([3, 12, -5, 10, 2]) # Simple lift sum = _lowlevel.lift_reduction_ckernel_deferred(ckd, 'strided * int32') out = nd.empty(ndt.int32) sum.__call__(out, in0) self.assertEqual(nd.as_py(out), 22) # Lift with keepdims sum = _lowlevel.lift_reduction_ckernel_deferred(ckd, 'strided * int32', keepdims=True) out = nd.empty(1, ndt.int32) sum.__call__(out, in0) self.assertEqual(nd.as_py(out), [22])
def check_from_numpy_int32_add(self, requiregil): # Get int32 add as a ckernel_deferred ckd = _lowlevel.ckernel_deferred_from_ufunc(np.add, (np.int32, np.int32, np.int32), requiregil) self.assertEqual(nd.as_py(ckd.types), [ndt.int32]*3) # Instantiate as a single kernel with _lowlevel.ckernel.CKernelBuilder() as ckb: meta = (ctypes.c_void_p * 3)() _lowlevel.ckernel_deferred_instantiate(ckd, ckb, 0, meta, "single") ck = ckb.ckernel(_lowlevel.ExprSingleOperation) a = ctypes.c_int32(10) b = ctypes.c_int32(21) c = ctypes.c_int32(0) src = (ctypes.c_void_p * 2)() src[0] = ctypes.addressof(a) src[1] = ctypes.addressof(b) ck(ctypes.addressof(c), src) self.assertEqual(c.value, 31) # Instantiate as a strided kernel with _lowlevel.ckernel.CKernelBuilder() as ckb: meta = (ctypes.c_void_p * 3)() _lowlevel.ckernel_deferred_instantiate(ckd, ckb, 0, meta, "strided") ck = ckb.ckernel(_lowlevel.ExprStridedOperation) a = (ctypes.c_int32 * 3)() b = (ctypes.c_int32 * 3)() c = (ctypes.c_int32 * 3)() for i, v in enumerate([1,4,6]): a[i] = v for i, v in enumerate([3, -1, 12]): b[i] = v src = (ctypes.c_void_p * 2)() src[0] = ctypes.addressof(a) src[1] = ctypes.addressof(b) strides = (c_ssize_t * 2)() strides[0] = strides[1] = 4 ck(ctypes.addressof(c), 4, src, strides, 3) self.assertEqual(c[0], 4) self.assertEqual(c[1], 3) self.assertEqual(c[2], 18)
floats = np.float32, np.float64 complexes = np.complex64, np.complex128, reductions = [('any', np.logical_or, False, bools), ('all', np.logical_and, True, bools), ('sum', np.add, 0, ints + floats + complexes), ('product', np.multiply, 1, ints + floats + complexes), ('min', np.minimum, None, bools + ints + floats + complexes), ('max', np.maximum, None, bools + ints + floats + complexes)] for name, np_op, ident, types in reductions: x = ReductionBlazeFunc('blaze', name) for typ in types: x.add_overload('(%s) -> %s' % (typ.__name__, typ.__name__), _lowlevel.ckernel_deferred_from_ufunc(np_op, (typ,) * 3, False), associative=True, commutative=True, identity=ident) locals()[name] = x #------------------------------------------------------------------------ # Other Funcs #------------------------------------------------------------------------ rolling_mean = RollingWindowBlazeFunc('blaze', 'rolling_mean') mean1d = _lowlevel.make_builtin_mean1d_ckernel_deferred('float64', 0) rolling_mean.add_overload('(M * float64) -> M * float64', mean1d) diff = BlazeFunc('blaze', 'diff') subtract_doubles_ck = _lowlevel.ckernel_deferred_from_ufunc(np.subtract,
#------------------------------------------------------------------------ real = blazefunc_from_dynd_property([ndt.complex_float32, ndt.complex_float64], 'real', 'blaze', 'real') imag = blazefunc_from_dynd_property([ndt.complex_float32, ndt.complex_float64], 'imag', 'blaze', 'imag') #------------------------------------------------------------------------ # Reduction UFuncs from NumPy #------------------------------------------------------------------------ any = ReductionBlazeFunc('blaze', 'any') any.add_overload('(bool) -> bool', _lowlevel.ckernel_deferred_from_ufunc(np.logical_or, (np.bool,) * 3, False), associative=True, commutative=True, identity=False) all = ReductionBlazeFunc('blaze', 'all') all.add_overload('(bool) -> bool', _lowlevel.ckernel_deferred_from_ufunc(np.logical_and, (np.bool,) * 3, False), associative=True, commutative=True, identity=True) sum = ReductionBlazeFunc('blaze', 'sum') for dt in [np.int32, np.int64, np.float32, np.float64, np.complex64, np.complex128]:
'date', 'blaze', 'date') time = blazefunc_from_dynd_property([ndt.datetime], 'time', 'blaze', 'time') #------------------------------------------------------------------------ # Reduction UFuncs from NumPy #------------------------------------------------------------------------ bools = np.bool, ints = np.int8, np.int16, np.int32, np.int64, floats = np.float32, np.float64 complexes = np.complex64, np.complex128, reductions = [('any', np.logical_or, False, bools), ('all', np.logical_and, True, bools), ('sum', np.add, 0, ints + floats + complexes), ('product', np.multiply, 1, ints + floats + complexes), ('min', np.minimum, None, bools + ints + floats + complexes), ('max', np.maximum, None, bools + ints + floats + complexes)] for name, np_op, ident, types in reductions: x = ReductionBlazeFunc('blaze', name) for typ in types: x.add_overload('(%s) -> %s' % (typ.__name__, typ.__name__), _lowlevel.ckernel_deferred_from_ufunc(np_op, (typ,) * 3, False), associative=True, commutative=True, identity=ident) locals()[name] = x