[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/NeutralCode/libgpuarray/master/pygpu/gpuarray.pyx [Back]  [Original]

cimport libc.stdio
from libc.stdlib cimport malloc, calloc, free
from cpython.mem cimport PyMem_Malloc, PyMem_Free
from libc.string cimport strncmp

cimport numpy as np
import numpy as np

from cpython cimport Py_INCREF, PyNumber_Index
from cpython.object cimport Py_EQ, Py_NE

def api_version():
    # major, minor, py
    return (gpuarray_api_major, gpuarray_api_minor, 0)

np.import_array()

# to export the numeric value
SIZE = GA_SIZE
SSIZE = GA_SSIZE

# Numpy API steals dtype references and this breaks cython
cdef object PyArray_Empty(int a, np.npy_intp *b, np.dtype c, int d):
    Py_INCREF(c)
    return _PyArray_Empty(a, b, c, d)

cdef bytes _s(s):
    if isinstance(s, unicode):
        return (s).encode('ascii')
    if isinstance(s, bytes):
        return s
    raise TypeError("Expected a string")

def cl_wrap_ctx(size_t ptr):
    """
    cl_wrap_ctx(ptr)

    Wrap an existing OpenCL context (the cl_context struct) into a
    GpuContext class.
    """
    cdef gpucontext *(*cl_make_ctx)(void *, int)
    cdef GpuContext res
    cl_make_ctx = gpuarray_get_extension("cl_make_ctx")
    if cl_make_ctx == NULL:
        raise RuntimeError, "cl_make_ctx extension is absent"
    res = GpuContext.__new__(GpuContext)
    res.ctx = cl_make_ctx(ptr, 0)
    if res.ctx == NULL:
        raise RuntimeError, "cl_make_ctx call failed"
    return res

def cuda_wrap_ctx(size_t ptr, bint own):
    """
    cuda_wrap_ctx(ptr)

    Wrap an existing CUDA driver context (CUcontext) into a GpuContext
    class.

    If `own` is true, libgpuarray is now reponsible for the context and
    it will be destroyed once there are no references to it.
    Otherwise, the context will not be destroyed and it is the calling
    code's reponsability.
    """
    cdef gpucontext *(*cuda_make_ctx)(void *, int)
    cdef int flags
    cdef GpuContext res
    cuda_make_ctx = gpuarray_get_extension("cuda_make_ctx")
    if cuda_make_ctx == NULL:
        raise RuntimeError, "cuda_make_ctx extension is absent"
    res = GpuContext.__new__(GpuContext)
    flags = 0
    if not own:
        flags |= GPUARRAY_CUDA_CTX_NOFREE
    res.ctx = cuda_make_ctx(ptr, flags)
    if res.ctx == NULL:
        raise RuntimeError, "cuda_make_ctx call failed"
    return res

import numpy

cdef dict NP_TO_TYPE = {
    np.dtype('bool'): GA_BOOL,
    np.dtype('int8'): GA_BYTE,
    np.dtype('uint8'): GA_UBYTE,
    np.dtype('int16'): GA_SHORT,
    np.dtype('uint16'): GA_USHORT,
    np.dtype('int32'): GA_INT,
    np.dtype('uint32'): GA_UINT,
    np.dtype('int64'): GA_LONG,
    np.dtype('uint64'): GA_ULONG,
    np.dtype('float32'): GA_FLOAT,
    np.dtype('float64'): GA_DOUBLE,
    np.dtype('complex64'): GA_CFLOAT,
    np.dtype('complex128'): GA_CDOUBLE,
    np.dtype('float16'): GA_HALF,
}

cdef dict TYPE_TO_NP = dict((v, k) for k, v in NP_TO_TYPE.iteritems())

def register_dtype(np.dtype dtype, cname):
    """
    register_dtype(dtype, cname)

    Make a new type known to the cluda machinery.

    This function return the associted internal typecode for the new
    type.

    :param dtype: new type
    :type dtype: numpy.dtype
    :param cname: C name for the type declarations
    :type cname: string
    :rtype: int
    """
    cdef gpuarray_type *t
    cdef int typecode
    cdef char *tmp

    t = malloc(sizeof(gpuarray_type))
    if t == NULL:
        raise MemoryError, "Can't allocate new type"
    tmp = malloc(len(cname)+1)
    if tmp == NULL:
        free(t)
        raise MemoryError
    memcpy(tmp, cname, len(cname)+1)
    t.size = dtype.itemsize
    t.align = dtype.alignment
    t.cluda_name = tmp
    typecode = gpuarray_register_type(t, NULL)
    if typecode == -1:
        free(tmp)
        free(t)
        raise RuntimeError, "Could not register type"
    NP_TO_TYPE[dtype] = typecode
    TYPE_TO_NP[typecode] = dtype

cdef np.dtype typecode_to_dtype(int typecode):
    res = TYPE_TO_NP.get(typecode, None)
    if res is not None:
        return res
    else:
        raise NotImplementedError, "TODO"

# This function takes a flexible dtype as accepted by the functions of
# this module and ensures it becomes a numpy dtype.
cdef np.dtype dtype_to_npdtype(dtype):
    if dtype is None:
        return None
    if isinstance(dtype, int):
        return typecode_to_dtype(dtype)
    try:
        return np.dtype(dtype)
    except TypeError:
        pass
    if isinstance(dtype, np.dtype):
        return dtype
    raise ValueError("data type not understood", dtype)

# This is a stupid wrapper to avoid the extra argument introduced by having
# dtype_to_typecode declared 'cpdef'.
cdef int get_typecode(dtype) except -1:
    return dtype_to_typecode(dtype)

cpdef int dtype_to_typecode(dtype) except -1:
    """
    dtype_to_typecode(dtype)

    Get the internal typecode for a type.

    :param dtype: type to get the code for
    :type dtype: numpy.dtype
    :rtype: int
    """
    if isinstance(dtype, int):
        return dtype
    try:
        dtype = np.dtype(dtype)
    except TypeError:
        pass
    if isinstance(dtype, np.dtype):
        res = NP_TO_TYPE.get(dtype, None)
        if res is not None:
            return res
    raise ValueError, "don't know how to convert to dtype: %s"%(dtype,)

def dtype_to_ctype(dtype):
    """
    dtype_to_ctype(dtype)

    Return the C name for a type.

    :param dtype: type to get the name for
    :type dtype: numpy.dtype
    :rtype: string
    """
    cdef int typecode = dtype_to_typecode(dtype)
    cdef const gpuarray_type *t = gpuarray_get_type(typecode)
    cdef bytes res
    if t.cluda_name == NULL:
        raise ValueError, "No mapping for %s"%(dtype,)
    res = t.cluda_name
    return res.decode('ascii')

cdef ga_order to_ga_order(ord) except -2:
    if ord == "C" or ord == "c":
        return GA_C_ORDER
    elif ord == "A" or ord == "a" or ord is None:
        return GA_ANY_ORDER
    elif ord == "F" or ord == "f":
        return GA_F_ORDER
    else:
        raise ValueError, "Valid orders are: 'A' (any), 'C' (C), 'F' (Fortran)"

class GpuArrayException(Exception):
    """
    Exception used for most errors related to libgpuarray.
    """

class UnsupportedException(GpuArrayException):
    pass

cdef type get_exc(int errcode):
    if errcode == GA_VALUE_ERROR:
        return ValueError
    if errcode == GA_DEVSUP_ERROR:
        return UnsupportedException
    else:
        return GpuArrayException

cdef bint py_CHKFLAGS(GpuArray a, int flags):
    return GpuArray_CHKFLAGS(&a.ga, flags)

cdef bint py_ISONESEGMENT(GpuArray a):
    return GpuArray_ISONESEGMENT(&a.ga)

cdef int array_empty(GpuArray a, gpucontext *ctx,
                     int typecode, unsigned int nd, const size_t *dims,
                     ga_order ord) except -1:
    cdef int err
    err = GpuArray_empty(&a.ga, ctx, typecode, nd, dims, ord)
    if err != GA_NO_ERROR:
        raise get_exc(err), gpucontext_error(ctx, err)

cdef int array_fromdata(GpuArray a,
                        gpudata *data, size_t offset, int typecode,
                        unsigned int nd, const size_t *dims,
                        const ssize_t *strides, int writeable) except -1:
    cdef int err
    err = GpuArray_fromdata(&a.ga, data, offset, typecode, nd, dims,
                            strides, writeable)
    if err != GA_NO_ERROR:
        raise get_exc(err), gpucontext_error(gpudata_context(data), err)

cdef int array_copy_from_host(GpuArray a,
                              gpucontext *ctx, void *buf, int typecode,
                              unsigned int nd, const size_t *dims,
                              const ssize_t *strides) except -1:
    cdef int err
    with nogil:
        err = GpuArray_copy_from_host(&a.ga, ctx, buf, typecode, nd, dims,
                                      strides);
    if err != GA_NO_ERROR:
        raise get_exc(err), gpucontext_error(ctx, err)

cdef int array_view(GpuArray v, GpuArray a) except -1:
    cdef int err
    err = GpuArray_view(&v.ga, &a.ga)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_sync(GpuArray a) except -1:
    cdef int err
    with nogil:
        err = GpuArray_sync(&a.ga)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_index(GpuArray r, GpuArray a, const ssize_t *starts,
                     const ssize_t *stops, const ssize_t *steps) except -1:
    cdef int err
    err = GpuArray_index(&r.ga, &a.ga, starts, stops, steps)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_take1(GpuArray r, GpuArray a, GpuArray i,
                     int check_err) except -1:
    cdef int err
    err = GpuArray_take1(&r.ga, &a.ga, &i.ga, check_err)
    if err != GA_NO_ERROR:
        if err == GA_VALUE_ERROR:
            raise IndexError, "Index out of bounds"
        raise get_exc(err), GpuArray_error(&r.ga, err)

cdef int array_setarray(GpuArray v, GpuArray a) except -1:
    cdef int err
    err = GpuArray_setarray(&v.ga, &a.ga)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&v.ga, err)

cdef int array_reshape(GpuArray res, GpuArray a, unsigned int nd,
                       const size_t *newdims, ga_order ord,
                       bint nocopy) except -1:
    cdef int err
    err = GpuArray_reshape(&res.ga, &a.ga, nd, newdims, ord, nocopy)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_transpose(GpuArray res, GpuArray a,
                         const unsigned int *new_axes) except -1:
    cdef int err
    err = GpuArray_transpose(&res.ga, &a.ga, new_axes)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_clear(GpuArray a) except -1:
    GpuArray_clear(&a.ga)

cdef bint array_share(GpuArray a, GpuArray b):
    return GpuArray_share(&a.ga, &b.ga)

cdef gpucontext *array_context(GpuArray a) except NULL:
    cdef gpucontext *res
    res = GpuArray_context(&a.ga)
    if res is NULL:
        raise GpuArrayException, "Invalid array or destroyed context"
    return res

cdef int array_move(GpuArray a, GpuArray src) except -1:
    cdef int err
    err = GpuArray_move(&a.ga, &src.ga)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_write(GpuArray a, void *src, size_t sz) except -1:
    cdef int err
    with nogil:
        err = GpuArray_write(&a.ga, src, sz)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_read(void *dst, size_t sz, GpuArray src) except -1:
    cdef int err
    with nogil:
        err = GpuArray_read(dst, sz, &src.ga)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&src.ga, err)

cdef int array_memset(GpuArray a, int data) except -1:
    cdef int err
    err = GpuArray_memset(&a.ga, data)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_copy(GpuArray res, GpuArray a, ga_order order) except -1:
    cdef int err
    err = GpuArray_copy(&res.ga, &a.ga, order)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_transfer(GpuArray res, GpuArray a) except -1:
    cdef int err
    with nogil:
        err = GpuArray_transfer(&res.ga, &a.ga)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_split(_GpuArray **res, GpuArray a, size_t n, size_t *p,
                     unsigned int axis) except -1:
    cdef int err
    err = GpuArray_split(res, &a.ga, n, p, axis)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(&a.ga, err)

cdef int array_concatenate(GpuArray r, const _GpuArray **a, size_t n,
                           unsigned int axis, int restype) except -1:
    cdef int err
    err = GpuArray_concatenate(&r.ga, a, n, axis, restype)
    if err != GA_NO_ERROR:
        raise get_exc(err), GpuArray_error(a[0], err)

cdef const char *kernel_error(GpuKernel k, int err) except NULL:
    return gpucontext_error(gpukernel_context(k.k.k), err)

cdef int kernel_init(GpuKernel k, gpucontext *ctx,
                     unsigned int count, const char **strs, const size_t *len,
                     const char *name, unsigned int argcount, const int *types,
                     int flags) except -1:
    cdef int err
    cdef char *err_str = NULL
    err = GpuKernel_init(&k.k, ctx, count, strs, len, name, argcount,
                          types, flags, &err_str)
    if err != GA_NO_ERROR:
        if err_str != NULL:
            try:
                py_err_str = err_str.decode('UTF-8')
            finally:
                free(err_str)
            raise get_exc(err), py_err_str
        raise get_exc(err), gpucontext_error(ctx, err)

cdef int kernel_clear(GpuKernel k) except -1:
    GpuKernel_clear(&k.k)

cdef gpucontext *kernel_context(GpuKernel k) except NULL:
    cdef gpucontext *res
    res = GpuKernel_context(&k.k)
    if res is NULL:
        raise GpuArrayException, "Invalid kernel or destroyed context"
    return res

cdef int kernel_sched(GpuKernel k, size_t n, size_t *ls, size_t *gs) except -1:
    cdef int err
    err = GpuKernel_sched(&k.k, n, ls, gs)
    if err != GA_NO_ERROR:
        raise get_exc(err), kernel_error(k, err)

cdef int kernel_call(GpuKernel k, unsigned int n, const size_t *ls,
                     const size_t *gs, size_t shared, void **args) except -1:
    cdef int err
    err = GpuKernel_call(&k.k, n, ls, gs, shared, args)
    if err != GA_NO_ERROR:
        raise get_exc(err), kernel_error(k, err)

cdef int kernel_binary(GpuKernel k, size_t *sz, void **bin) except -1:
    cdef int err
    err = GpuKernel_binary(&k.k, sz, bin)
    if err != GA_NO_ERROR:
        raise get_exc(err), kernel_error(k, err)

cdef int kernel_property(GpuKernel k, int prop_id, void *res) except -1:
    cdef int err
    err = gpukernel_property(k.k.k, prop_id, res)
    if err != GA_NO_ERROR:
        raise get_exc(err), kernel_error(k, err)

cdef GpuContext pygpu_default_context():
    return default_context

cdef GpuContext default_context = None

cdef int ctx_property(GpuContext c, int prop_id, void *res) except -1:
    cdef int err
    err = gpucontext_property(c.ctx, prop_id, res)
    if err != GA_NO_ERROR:
        raise get_exc(err), gpucontext_error(c.ctx, err)

def set_default_context(GpuContext ctx):
    """
    set_default_context(ctx)

    Set the default context for the module.

    :param ctx: default context
    :type ctx: GpuContext
    :rtype: None

    The provided context will be used as a default value for all the
    other functions in this module which take a context as parameter.
    Call with `None` to clear the default value.

    If you don't call this function the context of all other functions
    is a mandatory argument.

    This can be helpful to reduce clutter when working with only one
    context. It is strongly discouraged to use this function when
    working with multiple contexts at once.
    """
    global default_context
    default_context = ctx

def get_default_context():
    """
    get_default_context()

    Return the currently defined default context (or `None`).
    """
    return default_context

cdef GpuContext ensure_context(GpuContext c):
    global default_context
    if c is None:
        if default_context is None:
            raise TypeError, "No context specified."
        return default_context
    return c

cdef bint pygpu_GpuArray_Check(object o):
    return isinstance(o, GpuArray)

def count_platforms(kind):
    """Return number of host's platforms compatible with `kind`.
    """
    cdef unsigned int platcount
    cdef int err
    err = gpu_get_platform_count(_s(kind), &platcount)
    if err != GA_NO_ERROR:
        raise get_exc(err), gpucontext_error(NULL, err)
    return platcount

def count_devices(kind, unsigned int platform):
    """Returns number of devices in host's `platform` compatible with `kind`.
    """
    cdef unsigned int devcount
    cdef int err
    err = gpu_get_device_count(_s(kind), platform, &devcount)
    if err != GA_NO_ERROR:
        raise get_exc(err), gpucontext_error(NULL, err)
    return devcount

cdef GpuContext pygpu_init(dev, int flags):
    if dev.startswith('cuda'):
        kind = b"cuda"
        if dev[4:] == '':
            devnum = -1
        else:
            devnum = int(dev[4:])
    elif dev.startswith('opencl'):
        kind = b"opencl"
        devspec = dev[6:].split(':')
        if len(devspec) < 2:
            raise ValueError, "OpenCL name incorrect. Should be opencl: instead got: " + dev
        if not devspec[0].isdigit() or not devspec[1].isdigit():
            raise ValueError, "OpenCL name incorrect. Should be opencl: instead got: " + dev
        else:
            devnum = int(devspec[0]) 

Web Proxy Viewer  |  New URL  |  Original Page