Skip to content

Commit

Permalink
Merge branch 'master' of github.com:bh107/bohrium
Browse files Browse the repository at this point in the history
  • Loading branch information
safl committed Jun 8, 2015
2 parents 3b0e8e3 + c9fbfb4 commit bec390c
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 48 deletions.
39 changes: 22 additions & 17 deletions bridge/npbackend/ndarray.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -180,23 +180,28 @@ def get_bhc(ary):
raise ValueError("Bohrium arrays must be aligned, writeable, and in machine byte-order")
if not dtype_equal(ary, base):
raise ValueError("Bohrium base and view must have same data type")
if not base.ctypes.data <= ary.ctypes.data < base.ctypes.data + base.nbytes:
raise ValueError("The view must point to data within the base array")

# Lets make sure that 'ary' has a Bohrium-C base array
if base.bhc_ary is None:
base._data_np2bhc()

offset = (ary.ctypes.data - base.ctypes.data) / base.itemsize
if (ary.ctypes.data - base.ctypes.data) % base.itemsize != 0:
raise TypeError("The view offset must be element aligned")
if not 0 <= offset < base.size:
raise TypeError("The view offset is greater than the total number of elements in the base!")
strides = []
for stride in ary.strides:
strides.append(stride / base.itemsize)
if stride % base.itemsize != 0:
raise TypeError("The strides must be element aligned")

if 0 in ary.shape:#Lets use a dummy strides and offset for zero-sized views
strides = [0]*ary.ndim
offset = 0
else:
if not base.ctypes.data <= ary.ctypes.data < base.ctypes.data + base.nbytes:
raise ValueError("The view must point to data within the base array")

# Lets make sure that 'ary' has a Bohrium-C base array
if base.bhc_ary is None:
base._data_np2bhc()

offset = (ary.ctypes.data - base.ctypes.data) / base.itemsize
if (ary.ctypes.data - base.ctypes.data) % base.itemsize != 0:
raise TypeError("The view offset must be element aligned")
if not 0 <= offset < base.size:
raise TypeError("The view offset is greater than the total number of elements in the base!")
strides = []
for stride in ary.strides:
strides.append(stride / base.itemsize)
if stride % base.itemsize != 0:
raise TypeError("The strides must be element aligned")

ndim = ary.ndim if ary.ndim > 0 else 1
shape = ary.shape if len(ary.shape) > 0 else (1,)
Expand Down
10 changes: 9 additions & 1 deletion bridge/npbackend/src/_bhmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ typedef struct
int mmap_allocated;
}BhArray;

//Help function that returns number of bytes in 'ary'
//Help function that returns number of bytes in 'ary'
//BUT minimum 'itemsize', which mimic the behavior of NumPy
static int64_t ary_nbytes(const BhArray *ary)
{
Expand Down Expand Up @@ -522,6 +522,12 @@ BhArray_reshape(PyObject *self, PyObject *args)
return method2function("reshape", self, args);
}

static PyObject *
BhArray_flatten(PyObject *self, PyObject *args)
{
return method2function("flatten", self, args);
}

static PyObject *
BhArray_sum(PyObject *self, PyObject *args)
{
Expand All @@ -546,6 +552,8 @@ static PyMethodDef BhArrayMethods[] = {
{"reshape", BhArray_reshape, METH_VARARGS, "a.reshape(shape)\n\nReturns an array"
"containing the same data with a new shape.\n\n"
"Refer to `bohrium.reshape` for full documentation."},
{"flatten", BhArray_flatten, METH_VARARGS, "a.flatten()\n\nReturn a copy of the array collapsed into one dimension."},
{"ravel", BhArray_flatten, METH_VARARGS, "a.ravel()\n\nReturn a copy of the array collapsed into one dimension."},
{"sum", BhArray_sum, METH_VARARGS, "a.sum(axis=None, dtype=None, out=None)\n\n"
"Return the sum of the array elements over the given axis.\n\n"
"Refer to `bohrium.sum` for full documentation."},
Expand Down
70 changes: 40 additions & 30 deletions bridge/npbackend/target/target_bhc.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@
from .. import bhc
from .._util import dtype_name
from . import interface
import functools
import operator

class Base(interface.Base):
"""base array handle"""

def __init__(self, size, dtype, bhc_obj=None):
super(Base, self).__init__(size, dtype)
if size == 0:
return

if bhc_obj is None:
func = eval("bhc.bh_multi_array_%s_new_empty" % dtype_name(dtype))
bhc_obj = bhc_exec(func, 1, (size,))
bhc_obj = _bhc_exec(func, 1, (size,))
self.bhc_obj = bhc_obj

def __del__(self):
if self.size == 0:
return
exec("bhc.bh_multi_array_%s_destroy(self.bhc_obj)" %
dtype_name(self.dtype)
)
Expand All @@ -28,45 +34,36 @@ class View(interface.View):

def __init__(self, ndim, start, shape, strides, base):
super(View, self).__init__(ndim, start, shape, strides, base)
self.size = functools.reduce(operator.mul, shape, 1)
if self.size == 0:
return
dtype = dtype_name(self.dtype)
func = eval("bhc.bh_multi_array_%s_new_view" % dtype)
self.bhc_obj = func(base.bhc_obj, ndim, start, shape, strides)

def __del__(self):
if self.size == 0:
return
exec("bhc.bh_multi_array_%s_destroy(self.bhc_obj)" % dtype_name(
self.dtype
))

def views2bhc(views):
"""returns the bhc objects in the 'views' but don't touch scalars"""

singleton = not (hasattr(views, "__iter__") or
hasattr(views, "__getitem__"))
if singleton:
views = (views,)
ret = []
for view in views:
if not numpy.isscalar(view):
view = view.bhc_obj
ret.append(view)
if singleton:
ret = ret[0]
return ret

def bhc_exec(func, *args):
def _bhc_exec(func, *args):
"""execute the 'func' with the bhc objects in 'args'"""

args = list(args)
for i in xrange(len(args)):
if isinstance(args[i], View):
args[i] = views2bhc(args[i])
args[i] = args[i].bhc_obj
return func(*args)

def get_data_pointer(ary, allocate=False, nullify=False):
"""Retrieves the data pointer from Bohrium Runtime."""
if ary.size == 0 or ary.base.size == 0:
return 0

dtype = dtype_name(ary)
ary = views2bhc(ary)
ary = ary.bhc_obj
exec("bhc.bh_multi_array_%s_sync(ary)" % dtype)
exec("bhc.bh_multi_array_%s_discard(ary)" % dtype)
exec("bhc.bh_runtime_flush()")
Expand Down Expand Up @@ -110,6 +107,9 @@ def ufunc(op, *args):
scalar_str = "_scalar" + ("_rhs" if len(args) > 2 else "")
elif i > 0:
in_dtype = arg.dtype#overwrite with a non-scalar input
#Do nothing on zero-sized arguments
if arg.size == 0 or arg.base.size == 0:
return

if op.info['name'] == "identity":#Identity is a special case
cmd = "bhc.bh_multi_array_%s_identity_%s" % (
Expand All @@ -121,19 +121,21 @@ def ufunc(op, *args):
dtype_name(in_dtype), op.info['name']
)
cmd += scalar_str
bhc_exec(eval(cmd), *args)
_bhc_exec(eval(cmd), *args)

def reduce(op, out, ary, axis):
"""
reduce 'axis' dimension of 'ary' and write the result to out
:op npbackend.ufunc.Ufunc: Instance of a Ufunc.
"""
if ary.size == 0 or ary.base.size == 0:
return

func = eval("bhc.bh_multi_array_%s_%s_reduce" % (
dtype_name(ary), op.info['name']
))
bhc_exec(func, out, ary, axis)
_bhc_exec(func, out, ary, axis)

def accumulate(op, out, ary, axis):
"""
Expand All @@ -145,11 +147,13 @@ def accumulate(op, out, ary, axis):
:in2 ?:
:rtype: None
"""
if ary.size == 0 or ary.base.size == 0:
return

func = eval("bhc.bh_multi_array_%s_%s_accumulate" % (
dtype_name(ary), op.info['name'])
)
bhc_exec(func, out, ary, axis)
_bhc_exec(func, out, ary, axis)

def extmethod(name, out, in1, in2):
"""
Expand All @@ -162,13 +166,15 @@ def extmethod(name, out, in1, in2):
:in2 ?:
:rtype: None
"""
if out.size == 0 or out.base.size == 0:
return

func = eval("bhc.bh_multi_array_extmethod_%s_%s_%s" % (
dtype_name(out),
dtype_name(in1),
dtype_name(in2)
))
ret = bhc_exec(func, name, out, in1, in2)
ret = _bhc_exec(func, name, out, in1, in2)

if ret != 0:
raise NotImplementedError("The current runtime system does not support "
Expand All @@ -183,10 +189,12 @@ def range(size, dtype):
:rtype: None
"""

func = eval("bhc.bh_multi_array_%s_new_range" % dtype_name(dtype))
bhc_obj = bhc_exec(func, size)
if size > 0:
func = eval("bhc.bh_multi_array_%s_new_range"%dtype_name(dtype))
bhc_obj = _bhc_exec(func, size)
else:
bhc_obj = None
base = Base(size, dtype, bhc_obj)

return View(1, 0, (size,), (dtype.itemsize,), base)

def random123(size, start_index, key):
Expand All @@ -196,9 +204,11 @@ def random123(size, start_index, key):
"""

dtype = numpy.dtype("uint64")
func = eval("bhc.bh_multi_array_uint64_new_random123")
bhc_obj = bhc_exec(func, size, start_index, key)
if size > 0:
func = eval("bhc.bh_multi_array_uint64_new_random123")
bhc_obj = _bhc_exec(func, size, start_index, key)
else:
bhc_obj = None
base = Base(size, dtype, bhc_obj)

return View(1, 0, (size,), (dtype.itemsize,), base)

17 changes: 17 additions & 0 deletions test/python/test_emptiness.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import numpy as np
import bohrium as bh
from numpytest import numpytest,gen_views,TYPES


class test_empty(numpytest):

def init(self):
a = {}
cmd = "a[0] = bh.array([]);a[1] = bh.array([])"
exec(cmd)
yield (a, cmd)

def test_add(self,a):
cmd = "res = a[0] + a[1]"
exec(cmd)
return (res,cmd)
10 changes: 10 additions & 0 deletions test/python/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ def test_flatten(self,a):
exec(cmd)
return (res,cmd)

def test_flatten_self(self,a):
cmd = "res = a[0].flatten()"
exec(cmd)
return (res,cmd)

def test_ravel_self(self,a):
cmd = "res = a[0].ravel()"
exec(cmd)
return (res,cmd)

class test_diagonal(numpytest):

def init(self):
Expand Down

0 comments on commit bec390c

Please sign in to comment.