See More

# Hey Cython, this is Python 3! # cython: language_level=3 ########################################################################################### # Copyright INAOS GmbH, Thalwil, 2018. # Copyright Francesc Alted, 2018. # # All rights reserved. # # This software is the confidential and proprietary information of INAOS GmbH # and Francesc Alted ("Confidential Information"). You shall not disclose such Confidential # Information and shall use it only in accordance with the terms of the license agreement. ########################################################################################### from . cimport ciarray_ext as ciarray import numpy as np cimport numpy as np import cython from cpython.pycapsule cimport PyCapsule_New, PyCapsule_GetPointer from math import ceil from libc.stdlib cimport malloc, free import iarray as ia from collections import namedtuple class IArrayError(Exception): pass def iarray_check(error): if error != 0: raise IArrayError(str(ciarray.iarray_err_strerror(error))) IARRAY_ERR_EVAL_ENGINE_FAILED = ciarray.IARRAY_ERR_EVAL_ENGINE_FAILED IARRAY_ERR_EVAL_ENGINE_NOT_COMPILED = ciarray.IARRAY_ERR_EVAL_ENGINE_NOT_COMPILED IARRAY_ERR_EVAL_ENGINE_OUT_OF_RANGE = ciarray.IARRAY_ERR_EVAL_ENGINE_OUT_OF_RANGE cdef set_storage(storage, ciarray.iarray_storage_t *cstore): cstore.enforce_frame = storage.enforce_frame if storage.plainbuffer: cstore.backend = ciarray.IARRAY_STORAGE_PLAINBUFFER else: cstore.backend = ciarray.IARRAY_STORAGE_BLOSC for i in range(len(storage.chunks)): cstore.chunkshape[i] = storage.chunks[i] cstore.blockshape[i] = storage.blocks[i] if storage.urlpath is not None: urlpath = storage.urlpath.encode("utf-8") if isinstance(storage.urlpath, str) else storage.urlpath cstore.urlpath = storage.urlpath else: cstore.urlpath = NULL cdef class ReadBlockIter: cdef ciarray.iarray_iter_read_block_t *ia_read_iter cdef ciarray.iarray_iter_read_block_value_t ia_block_val cdef Container container cdef int dtype cdef int flag cdef object Info def __cinit__(self, container, block): self.container = container cdef ciarray.int64_t block_[ciarray.IARRAY_DIMENSION_MAX] if block is None: block = container.chunks for i in range(len(block)): block_[i] = block[i] iarray_check(ciarray.iarray_iter_read_block_new(self.container.context.ia_ctx, &self.ia_read_iter, self.container.ia_container, block_, &self.ia_block_val, False)) if self.container.dtype == np.float64: self.dtype = 0 else: self.dtype = 1 self.Info = namedtuple('Info', 'index elemindex nblock shape size slice') def __dealloc__(self): ciarray.iarray_iter_read_block_free(&self.ia_read_iter) def __iter__(self): return self def __next__(self): if ciarray.iarray_iter_read_block_has_next(self.ia_read_iter) != 0: raise StopIteration iarray_check(ciarray.iarray_iter_read_block_next(self.ia_read_iter, NULL, 0)) shape = tuple(self.ia_block_val.block_shape[i] for i in range(self.container.ndim)) size = np.prod(shape) if self.dtype == 0: view = self.ia_block_val.block_pointer else: view = self.ia_block_val.block_pointer a = np.asarray(view) elem_index = tuple(self.ia_block_val.elem_index[i] for i in range(self.container.ndim)) index = tuple(self.ia_block_val.block_index[i] for i in range(self.container.ndim)) nblock = self.ia_block_val.nblock slice_ = tuple([slice(i, i + s) for i, s in zip(elem_index, shape)]) info = self.Info(index=index, elemindex=elem_index, nblock=nblock, shape=shape, size=size, slice=slice_) return info, a.reshape(shape) cdef class WriteBlockIter: cdef ciarray.iarray_iter_write_block_t *ia_write_iter cdef ciarray.iarray_iter_write_block_value_t ia_block_val cdef Container container cdef int dtype cdef int flag cdef object Info def __cinit__(self, c, block=None): self.container = c cdef ciarray.int64_t block_[ciarray.IARRAY_DIMENSION_MAX] if block is None: # The block for iteration has always be provided block = c.chunks for i in range(len(block)): block_[i] = block[i] iarray_check(ciarray.iarray_iter_write_block_new(self.container.context.ia_ctx, &self.ia_write_iter, self.container.ia_container, block_, &self.ia_block_val, False)) if self.container.dtype == np.float64: self.dtype = 0 else: self.dtype = 1 self.Info = namedtuple('Info', 'index elemindex nblock shape size') def __dealloc__(self): ciarray.iarray_iter_write_block_free(&self.ia_write_iter) def __iter__(self): return self def __next__(self): if ciarray.iarray_iter_write_block_has_next(self.ia_write_iter) != 0: raise StopIteration iarray_check(ciarray.iarray_iter_write_block_next(self.ia_write_iter, NULL, 0)) shape = tuple(self.ia_block_val.block_shape[i] for i in range(self.container.ndim)) size = np.prod(shape) if self.dtype == 0: view = self.ia_block_val.block_pointer else: view = self.ia_block_val.block_pointer a = np.asarray(view) elem_index = tuple(self.ia_block_val.elem_index[i] for i in range(self.container.ndim)) index = tuple(self.ia_block_val.block_index[i] for i in range(self.container.ndim)) nblock = self.ia_block_val.nblock info = self.Info(index=index, elemindex=elem_index, nblock=nblock, shape=shape, size=size) return info, a.reshape(shape) cdef class IArrayInit: def __cinit__(self): iarray_check(ciarray.iarray_init()) def __dealloc__(self): ciarray.iarray_destroy() cdef class Config: cdef ciarray.iarray_config_t config def __init__(self, compression_codec, compression_level, compression_favor, use_dict, filters, max_num_threads, fp_mantissa_bits, eval_method, btune): self.config.compression_codec = compression_codec.value self.config.compression_level = compression_level self.config.compression_favor = compression_favor.value self.config.use_dict = 1 if use_dict else 0 cdef int filter_flags = 0 # TODO: filters are really a pipeline, and here we are just ORing them, which is tricky. # This should be fixed (probably at C iArray level and then propagating the change here). # At any rate, `filters` should be a list for displaying purposes in high level Config(). for f in filters: filter_flags |= f.value if fp_mantissa_bits > 0: filter_flags |= ia.Filters.TRUNC_PREC.value self.config.filter_flags = filter_flags if eval_method == ia.Eval.AUTO: method = ciarray.IARRAY_EVAL_METHOD_AUTO elif eval_method == ia.Eval.ITERBLOSC: method = ciarray.IARRAY_EVAL_METHOD_ITERBLOSC elif eval_method == ia.Eval.ITERCHUNK: method = ciarray.IARRAY_EVAL_METHOD_ITERCHUNK else: raise ValueError("eval_method method not recognized:", eval_method) self.config.eval_method = method self.config.max_num_threads = max_num_threads self.config.fp_mantissa_bits = fp_mantissa_bits self.config.btune = btune def _to_dict(self): return self.config cdef class Context: cdef ciarray.iarray_context_t *ia_ctx def __init__(self, cfg): cdef ciarray.iarray_config_t cfg_ = cfg._to_dict() iarray_check(ciarray.iarray_context_new(&cfg_, &self.ia_ctx)) def __dealloc__(self): ciarray.iarray_context_free(&self.ia_ctx) def to_capsule(self): return PyCapsule_New(self.ia_ctx, "iarray_context_t*", NULL) cdef class IaDTShape: cdef ciarray.iarray_dtshape_t ia_dtshape def __cinit__(self, dtshape): self.ia_dtshape.ndim = len(dtshape.shape) if dtshape.dtype == np.float64: self.ia_dtshape.dtype = ciarray.IARRAY_DATA_TYPE_DOUBLE elif dtshape.dtype == np.float32: self.ia_dtshape.dtype = ciarray.IARRAY_DATA_TYPE_FLOAT for i in range(len(dtshape.shape)): self.ia_dtshape.shape[i] = dtshape.shape[i] cdef to_dict(self): return self.ia_dtshape @property def ndim(self): return self.ia_dtshape.ndim @property def dtype(self): dtype = [np.float64, np.float32] return dtype[self.ia_dtshape.dtype] @property def shape(self): shape = [] for i in range(self.ndim): shape.append(self.ia_dtshape.shape[i]) return tuple(shape) def __str__(self): return self.ia_dtshape cdef class RandomContext: cdef ciarray.iarray_random_ctx_t *random_ctx cdef Context context def __init__(self, ctx, seed, rng): self.context = ctx cdef ciarray.iarray_random_ctx_t* r_ctx if rng == ia.RandomGen.MERSENNE_TWISTER: iarray_check(ciarray.iarray_random_ctx_new(self.context.ia_ctx, seed, ciarray.IARRAY_RANDOM_RNG_MERSENNE_TWISTER, &r_ctx)) elif rng == ia.RandomGen.SOBOL: iarray_check(ciarray.iarray_random_ctx_new(self.context.ia_ctx, seed, ciarray.IARRAY_RANDOM_RNG_SOBOL, &r_ctx)) else: raise ValueError("Random generator unknown") self.random_ctx = r_ctx def __dealloc__(self): if self.context is not None and self.context.ia_ctx != NULL: ciarray.iarray_random_ctx_free(self.context.ia_ctx, &self.random_ctx) self.context = None def to_capsule(self): return PyCapsule_New(self.random_ctx, "iarray_random_ctx_t*", NULL) cdef class Container: cdef ciarray.iarray_container_t *ia_container cdef Context context def __init__(self, ctx, c): if ctx is None: raise ValueError("You must pass a context to the Container constructor") if c is None: raise ValueError("You must pass a Capsule to the C container struct of the Container constructor") self.context = ctx cdef ciarray.iarray_container_t* c_ = PyCapsule_GetPointer( c, "iarray_container_t*") self.ia_container = c_ def __dealloc__(self): if self.context is not None and self.context.ia_ctx != NULL: ciarray.iarray_container_free(self.context.ia_ctx, &self.ia_container) self.context = None def to_capsule(self): return PyCapsule_New(self.ia_container, "iarray_container_t*", NULL) @property def ndim(self): """Number of array dimensions.""" cdef ciarray.iarray_dtshape_t dtshape iarray_check(ciarray.iarray_get_dtshape(self.context.ia_ctx, self.ia_container, &dtshape)) return dtshape.ndim @property def shape(self): """Tuple of array dimensions.""" cdef ciarray.iarray_dtshape_t dtshape iarray_check(ciarray.iarray_get_dtshape(self.context.ia_ctx, self.ia_container, &dtshape)) shape = [dtshape.shape[i] for i in range(self.ndim)] return tuple(shape) @property def is_plainbuffer(self): """bool indicating if the container is based on a plainbuffer or not""" cdef ciarray.iarray_storage_t storage iarray_check(ciarray.iarray_get_storage(self.context.ia_ctx, self.ia_container, &storage)) if storage.backend == ciarray.IARRAY_STORAGE_PLAINBUFFER: return True else: return False @property def chunks(self): """Tuple of chunk dimensions.""" cdef ciarray.iarray_storage_t storage iarray_check(ciarray.iarray_get_storage(self.context.ia_ctx, self.ia_container, &storage)) if storage.backend == ciarray.IARRAY_STORAGE_PLAINBUFFER or self.is_view(): return None chunks = [storage.chunkshape[i] for i in range(self.ndim)] return tuple(chunks) @property def blocks(self): """Tuple of block dimensions.""" cdef ciarray.iarray_storage_t storage iarray_check(ciarray.iarray_get_storage(self.context.ia_ctx, self.ia_container, &storage)) if storage.backend == ciarray.IARRAY_STORAGE_PLAINBUFFER or self.is_view(): return None blocks = [storage.blockshape[i] for i in range(self.ndim)] return tuple(blocks) @property def dtype(self): """Data-type of the array’s elements.""" dtype = [np.float64, np.float32] cdef ciarray.iarray_dtshape_t dtshape iarray_check(ciarray.iarray_get_dtshape(self.context.ia_ctx, self.ia_container, &dtshape)) return dtype[dtshape.dtype] @property def dtshape(self): """The :py:obj:`DTShape` of the array.""" return ia.DTShape(self.shape, self.dtype) @property def cratio(self): """Array compression ratio""" cdef ciarray.int64_t nbytes, cbytes iarray_check(ciarray.iarray_container_info(self.ia_container, &nbytes, &cbytes)) return nbytes / cbytes def __getitem__(self, key): # key has been massaged already start, stop, squeeze_mask = key return get_slice(self.context, self, start, stop, squeeze_mask, True, None) def is_view(self): cdef ciarray.bool view iarray_check(ciarray.iarray_is_view(self.context.ia_ctx, self.ia_container, &view)) return view cdef class Expression: cdef object expression cdef ciarray.iarray_expression_t *ia_expr cdef Context context def __init__(self, cfg): self.context = Context(cfg) cdef ciarray.iarray_expression_t* e iarray_check(ciarray.iarray_expr_new(self.context.ia_ctx, &e)) self.ia_expr = e self.expression = None self.storage = None self.dtshape = None def __dealloc__(self): if self.context is not None and self.context.ia_ctx != NULL: ciarray.iarray_expr_free(self.context.ia_ctx, &self.ia_expr) self.context = None def bind(self, var, c): var2 = var.encode("utf-8") if isinstance(var, str) else var cdef ciarray.iarray_container_t *c_ = PyCapsule_GetPointer( c.to_capsule(), "iarray_container_t*") iarray_check(ciarray.iarray_expr_bind(self.ia_expr, var2, c_)) def bind_out_properties(self, dtshape, storage): dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(storage, &store_) iarray_check(ciarray.iarray_expr_bind_out_properties(self.ia_expr, &dtshape_, &store_)) self.dtshape = dtshape self.storage = storage def compile(self, expr): # Try to support all the ufuncs in numpy ufunc_repls = { "arcsin": "asin", "arccos": "acos", "arctan": "atan", "arctan2": "atan2", "power": "pow", } for ufunc in ufunc_repls.keys(): if ufunc in expr: expr = expr.replace(ufunc, ufunc_repls[ufunc]) expr = expr.encode("utf-8") if isinstance(expr, str) else expr iarray_check(ciarray.iarray_expr_compile(self.ia_expr, expr)) self.expression = expr def compile_bc(self, bc, name): name = name.encode() iarray_check(ciarray.iarray_expr_compile_udf(self.ia_expr, len(bc), bc, name)) self.expression = "user_defined_function" def compile_udf(self, func): self.compile_bc(func.bc, func.name) def eval(self): cdef ciarray.iarray_container_t *c; with nogil: error = ciarray.iarray_eval(self.ia_expr, &c) iarray_check(error) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(self.context, c_c) # # Iarray container constructors # def copy(cfg, src, view=False): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) cdef int flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c cdef ciarray.iarray_container_t *src_ = PyCapsule_GetPointer( src.to_capsule(), "iarray_container_t*") cdef int view_ = view with nogil: error = ciarray.iarray_copy(ctx_, src_, view_, &store_, flags, &c) iarray_check(error) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def empty(cfg, dtshape): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_container_new(ctx_, &dtshape_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def arange(cfg, slice_, dtshape): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") start, stop, step = slice_.start, slice_.stop, slice_.step dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_arange(ctx_, &dtshape_, start, stop, step, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def linspace(cfg, start, stop, dtshape): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_linspace(ctx_, &dtshape_, start, stop, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def zeros(cfg, dtshape): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_zeros(ctx_, &dtshape_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def ones(cfg, dtshape): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_ones(ctx_, &dtshape_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def full(cfg, fill_value, dtshape): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c if dtshape["dtype"] == ciarray.IARRAY_DATA_TYPE_DOUBLE: iarray_check(ciarray.iarray_fill_double(ctx_, &dtshape_, fill_value, &store_, flags, &c)) else: iarray_check(ciarray.iarray_fill_float(ctx_, &dtshape_, fill_value, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def load(cfg, urlpath): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") urlpath = urlpath.encode("utf-8") if isinstance(urlpath, str) else urlpath cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_container_load(ctx_, urlpath, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def open(cfg, urlpath): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") urlpath = urlpath.encode("utf-8") if isinstance(urlpath, str) else urlpath cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_container_open(ctx_, urlpath, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def get_slice(ctx, data, start, stop, squeeze_mask, view, storage): cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_container_t *data_ = PyCapsule_GetPointer( data.to_capsule(), "iarray_container_t*") shape = [sp%s - st%s for sp, st, s in zip(stop, start, data.shape)] dtshape = ia.DTShape(shape, data.dtype) flags = 0 cdef ciarray.int64_t start_[ciarray.IARRAY_DIMENSION_MAX] cdef ciarray.int64_t stop_[ciarray.IARRAY_DIMENSION_MAX] for i in range(len(start)): start_[i] = start[i] stop_[i] = stop[i] cdef ciarray.iarray_storage_t store_ cdef ciarray.iarray_container_t *c if view: iarray_check(ciarray.iarray_get_slice(ctx_, data_, start_, stop_, view, NULL, flags, &c)) else: set_storage(storage, &store_) iarray_check(ciarray.iarray_get_slice(ctx_, data_, start_, stop_, view, &store_, flags, &c)) cdef ciarray.bool squeeze_mask_[ciarray.IARRAY_DIMENSION_MAX] for i in range(data.ndim): squeeze_mask_[i] = squeeze_mask[i] iarray_check(ciarray.iarray_squeeze_index(ctx_, c, squeeze_mask_)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) b = ia.IArray(ctx, c_c) if b.ndim == 0: return float(ia.iarray2numpy(b)) return b def numpy2iarray(cfg, a, dtshape): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST buffer_size = a.size * np.dtype(a.dtype).itemsize cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_from_buffer(ctx_, &dtshape_, np.PyArray_DATA(a), buffer_size, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def iarray2numpy(cfg, c): ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer( ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_container_t *c_ = PyCapsule_GetPointer( c.to_capsule(), "iarray_container_t*") cdef ciarray.iarray_dtshape_t dtshape iarray_check(ciarray.iarray_get_dtshape(ctx_, c_, &dtshape)) shape = [] for i in range(dtshape.ndim): shape.append(dtshape.shape[i]) size = np.prod(shape, dtype=np.int64) dtype = np.float64 if dtshape.dtype == ciarray.IARRAY_DATA_TYPE_DOUBLE else np.float32 if ciarray.iarray_is_empty(c_): # Return an empty array. Another possibility would be to raise an exception here? Let's wait for a use case... return np.empty(size, dtype=dtype).reshape(shape) a = np.zeros(size, dtype=dtype).reshape(shape) iarray_check(ciarray.iarray_to_buffer(ctx_, c_, np.PyArray_DATA(a), size * sizeof(dtype))) return a # # Random functions # def random_rand(cfg, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_rand(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_randn(cfg, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_randn(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_beta(cfg, alpha, beta, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") if dtshape.dtype == np.float64: ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_ALPHA, alpha) ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_BETA, beta) else: ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_ALPHA, alpha) ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_BETA, beta) dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_beta(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_lognormal(cfg, mu, sigma, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") if dtshape.dtype == np.float64: ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_MU, mu) ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_SIGMA, sigma) else: ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_MU, mu) ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_SIGMA, sigma) dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_lognormal(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_exponential(cfg, beta, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") if dtshape.dtype == np.float64: iarray_check(ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_BETA, beta)) else: iarray_check(ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_BETA, beta)) dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_exponential(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_uniform(cfg, a, b, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") if dtshape.dtype == np.float64: iarray_check(ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_A, a)) iarray_check(ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_B, b)) else: iarray_check(ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_A, a)) iarray_check(ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_B, b)) dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_uniform(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_normal(cfg, mu, sigma, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") if dtshape.dtype == np.float64: iarray_check(ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_MU, mu)) iarray_check(ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_SIGMA, sigma)) else: iarray_check(ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_MU, mu)) iarray_check(ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_SIGMA, sigma)) dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_normal(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_bernoulli(cfg, p, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") if dtshape.dtype == np.float64: iarray_check(ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_P, p)) else: iarray_check(ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_P, p)) dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_bernoulli(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_binomial(cfg, m, p, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") if dtshape.dtype == np.float64: iarray_check(ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_P, p)) iarray_check(ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_M, m)) else: iarray_check(ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_P, p)) iarray_check(ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_M, m)) dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_binomial(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_poisson(cfg, l, dtshape): ctx = Context(cfg) r_ctx = RandomContext(ctx, cfg.seed, cfg.random_gen) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_random_ctx_t *r_ctx_ = PyCapsule_GetPointer(r_ctx.to_capsule(), "iarray_random_ctx_t*") if dtshape.dtype == np.float64: iarray_check(ciarray.iarray_random_dist_set_param_double(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_LAMBDA, l)) else: iarray_check(ciarray.iarray_random_dist_set_param_float(r_ctx_, ciarray.IARRAY_RANDOM_DIST_PARAM_LAMBDA, l)) dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = dtshape cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) flags = 0 if cfg.store.urlpath is None else ciarray.IARRAY_CONTAINER_PERSIST cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_random_poisson(ctx_, &dtshape_, r_ctx_, &store_, flags, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def random_kstest(cfg, a, b): ctx = Context(cfg) cdef ciarray.iarray_container_t *a_ = PyCapsule_GetPointer(a.to_capsule(), "iarray_container_t*") cdef ciarray.iarray_container_t *b_ = PyCapsule_GetPointer(b.to_capsule(), "iarray_container_t*") cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.bool res; iarray_check(ciarray.iarray_random_kstest(ctx_, a_, b_, &res)) return res def matmul(cfg, a, b): ctx = Context(cfg) cdef ciarray.iarray_container_t *a_ = PyCapsule_GetPointer(a.to_capsule(), "iarray_container_t*") cdef ciarray.iarray_container_t *b_ = PyCapsule_GetPointer(b.to_capsule(), "iarray_container_t*") cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_container_t *c cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) iarray_check(ciarray.iarray_linalg_matmul(ctx_, a_, b_, &store_, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def transpose(cfg, a): ctx = Context(cfg) cdef ciarray.iarray_container_t *a_ = PyCapsule_GetPointer(a.to_capsule(), "iarray_container_t*") cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_container_t *c iarray_check(ciarray.iarray_linalg_transpose(ctx_, a_, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) # Reductions reduce_to_c = { ia.Reduce.MAX: ciarray.IARRAY_REDUCE_MAX, ia.Reduce.MIN: ciarray.IARRAY_REDUCE_MIN, ia.Reduce.SUM: ciarray.IARRAY_REDUCE_SUM, ia.Reduce.PROD: ciarray.IARRAY_REDUCE_PROD, ia.Reduce.MEAN: ciarray.IARRAY_REDUCE_MEAN, } def reduce(cfg, a, method, axis): ctx = Context(cfg) cdef ciarray.iarray_reduce_func_t func = reduce_to_c[method] cdef ciarray.iarray_container_t *a_ = PyCapsule_GetPointer(a.to_capsule(), "iarray_container_t*") cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_container_t *c cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) iarray_check(ciarray.iarray_reduce(ctx_, a_, func, axis, &store_, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def reduce_multi(cfg, a, method, axis): ctx = Context(cfg) cdef ciarray.iarray_reduce_func_t func = reduce_to_c[method] cdef ciarray.iarray_container_t *a_ = PyCapsule_GetPointer(a.to_capsule(), "iarray_container_t*") cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") cdef ciarray.iarray_container_t *c cdef ciarray.int8_t axis_[ciarray.IARRAY_DIMENSION_MAX] for i, ax in enumerate(axis): axis_[i] = ax cdef ciarray.iarray_storage_t store_ set_storage(cfg.store, &store_) iarray_check(ciarray.iarray_reduce_multi(ctx_, a_, func, len(axis), axis_, &store_, &c)) c_c = PyCapsule_New(c, "iarray_container_t*", NULL) return ia.IArray(ctx, c_c) def get_ncores(max_ncores): cdef int ncores = 1 try: iarray_check(ciarray.iarray_get_ncores(&ncores, max_ncores)) except IArrayError: # In case of error, return a negative value return -1 return ncores def partition_advice(dtshape, min_chunksize, max_chunksize, min_blocksize, max_blocksize, cfg): _dtshape = IaDTShape(dtshape).to_dict() cdef ciarray.iarray_dtshape_t dtshape_ = _dtshape ctx = Context(cfg) cdef ciarray.iarray_context_t *ctx_ = PyCapsule_GetPointer(ctx.to_capsule(), "iarray_context_t*") # Create a storage struct and initialize it. Do we really need a store for this (maybe a frame info)? cdef ciarray.iarray_storage_t store store.backend = ciarray.IARRAY_STORAGE_BLOSC store.enforce_frame = False # Ask for the actual advice try: iarray_check(ciarray.iarray_partition_advice(ctx_, &dtshape_, &store, min_chunksize, max_chunksize, min_blocksize, max_blocksize)) except: return None, None # Extract the shapes and return them as tuples chunks = tuple(store.chunkshape[i] for i in range(len(dtshape.shape))) blocks = tuple(store.blockshape[i] for i in range(len(dtshape.shape))) return chunks, blocks # # TODO: the next functions are just for benchmarking purposes and should be moved to its own extension # cimport numpy as cnp @cython.boundscheck(False) # turn off bounds-checking for entire function @cython.wraparound(False) # turn off negative index wrapping for entire function def poly_cython(xa): shape = xa.shape cdef np.ndarray[cnp.npy_float64] y = np.empty(xa.shape, xa.dtype).flatten() cdef np.ndarray[cnp.npy_float64] x = xa.flatten() for i in range(len(x)): y[i] = (x[i] - 1.35) * (x[i] - 4.45) * (x[i] - 8.5) return y.reshape(shape) # from cython.parallel import prange @cython.boundscheck(False) # turn off bounds-checking for entire function @cython.wraparound(False) # turn off negative index wrapping for entire function cdef void poly_nogil(double *x, double *y, int n) nogil: cdef int i # for i in prange(n): for i in range(n): y[i] = (x[i] - 1.35) * (x[i] - 4.45) * (x[i] - 8.5) def poly_cython_nogil(xa): shape = xa.shape cdef np.ndarray[cnp.npy_float64] y = np.empty(xa.shape, xa.dtype).flatten() cdef np.ndarray[cnp.npy_float64] x = xa.flatten() poly_nogil(&x[0], &y[0], len(x)) return y.reshape(shape) # TODO: End of the benchmarking code