Commit 2c2f0f2b authored by Mat's avatar Mat
Browse files

Initial import

parents
Loading
Loading
Loading
Loading

.gitignore

0 → 100644
+2 −0
Original line number Diff line number Diff line
/build
*.so

setup.py

0 → 100755
+18 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3
##
##      Project: SharedArray
## 
##         File: setup.py
## 
##  Description: Setup script
## 
##     Author/s: Mathieu Mirmont <mat@parad0x.org>
## 
##   Created on: 08/12/2014
## 
##

from distutils.core import setup, Extension
from glob import glob

setup(ext_modules = [ Extension("SharedArray", glob("src/*.c")) ])

src/shared_array.c

0 → 100644
+68 −0
Original line number Diff line number Diff line
/*
 *      Project: SharedArray
 * 
 *         File: src/shared_array.c
 * 
 *  Description: SharedArray module definition
 * 
 *     Author/s: Mathieu Mirmont <mat@parad0x.org>
 * 
 *   Created on: 08/12/2014
 * 
 */

#define NPY_NO_DEPRECATED_API	NPY_1_8_API_VERSION
#define PY_ARRAY_UNIQUE_SYMBOL	SHARED_ARRAY_ARRAY_API

#include <Python.h>
#include <numpy/arrayobject.h>
#include "shared_array.h"
#include "shared_array_leon.h"

/*
 * Module functions
 */
static PyMethodDef module_functions[] = {
	{ "create", (PyCFunction) shared_array_create,
	  METH_VARARGS | METH_KEYWORDS, "Create a numpy array in shared memory" },
	{ NULL, NULL, 0, NULL }
};

/*
 * Module definition
 */
static struct PyModuleDef module_def = {
        PyModuleDef_HEAD_INIT,
	"SharedArray",
	"This module lets you share numpy arrays between several python interpreters",
        -1,
        module_functions,
        NULL,
        NULL,
        NULL,
        NULL,
};

/*
 * Module initialisation
 */
PyMODINIT_FUNC PyInit_SharedArray(void)
{
	PyObject *m;

	/* Ready our type */
	if (PyType_Ready(&PyLeonObject_Type) < 0)
		return NULL;

	/* Register our module */
	if (!(m = PyModule_Create(&module_def)))
		return NULL;

	/* Register our type */
	Py_INCREF(&PyLeonObject_Type);
	PyModule_AddObject(m, "SharedArray", (PyObject *) &PyLeonObject_Type);
	
	/* Import numpy arrays */
	import_array();
	return m;
}

src/shared_array.h

0 → 100644
+36 −0
Original line number Diff line number Diff line
/*
 *      Project: SharedArray
 * 
 *         File: src/shared_array.h
 * 
 *  Description: SharedArray module definition
 * 
 *     Author/s: Mathieu Mirmont <mat@parad0x.org>
 * 
 *   Created on: 08/12/2014
 * 
 */

#ifndef __SHARED_ARRAY_H__
#define __SHARED_ARRAY_H__

#include <Python.h>
#include <numpy/arrayobject.h>

/* Magic header */
#define SHARED_ARRAY_MAGIC	"[SharedArray]"

/* Maximum number of dimensions */
#define SHARED_ARRAY_NDIMS_MAX	16

/* Array metadata */
struct array_meta {
	char magic[16];
	uint32_t ndims;
	uint32_t dims[SHARED_ARRAY_NDIMS_MAX];
} __attribute__ ((packed));

/* Module functions */
extern PyObject *shared_array_create(PyObject *self, PyObject *args, PyObject *kw);

#endif /* !__SHARED_ARRAY_H__ */
+120 −0
Original line number Diff line number Diff line
/*
 *      Project: SharedArray
 * 
 *         File: src/shared_array_create.c
 * 
 *  Description: Create a numpy array in shared memory
 * 
 *     Author/s: Mathieu Mirmont <mat@parad0x.org>
 * 
 *   Created on: 08/12/2014
 * 
 */

#define NPY_NO_DEPRECATED_API	NPY_1_8_API_VERSION
#define PY_ARRAY_UNIQUE_SYMBOL	SHARED_ARRAY_ARRAY_API
#define NO_IMPORT_ARRAY

#include <Python.h>
#include <numpy/arrayobject.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "shared_array.h"
#include "shared_array_leon.h"

/*
 * Create a numpy array in shared memory
 */
static PyObject *do_create(const char *name, int ndims, npy_intp *dims, PyArray_Descr *dtype)
{
	struct array_meta *meta;
	void *data;
	size_t size;
	int i;
	int fd;
	PyObject *ret;
	PyLeonObject *leon;

	/* Internal limitation */
	if (ndims > SHARED_ARRAY_NDIMS_MAX) {
		PyErr_SetString(PyExc_RuntimeError, "Too many dimensions, recompile SharedArray!");
		return NULL;
	}

	/* Calculate the size of the memory to allocate */
	size = dtype->elsize;
	for (i = 0; i < ndims; i++)
		size *= dims[i];
	size += sizeof (*meta);

	/* Create the shm block */
	if ((fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0)
		return PyErr_SetFromErrno(PyExc_RuntimeError);

	/* Set the block size */
	if (ftruncate(fd, size) < 0)
		return PyErr_SetFromErrno(PyExc_RuntimeError);

	/* Map it */
	data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	close(fd);
	if (data == MAP_FAILED)
		return PyErr_SetFromErrno(PyExc_RuntimeError);

	/* Build the meta-data structure in memory */
	meta = (struct array_meta *) data;
	strncpy(meta->magic, SHARED_ARRAY_MAGIC, sizeof (meta->magic));
	meta->ndims = ndims;
	for (i = 0; i < ndims; i++)
		meta->dims[i] = dims[i];

	/* Summon Leon */
	leon = PyObject_MALLOC(sizeof (*leon));
	PyObject_INIT((PyObject *) leon, &PyLeonObject_Type);
	leon->data = data;
	leon->size = size;

	/* Skip the meta-data and point to the raw data */
	data += sizeof (*meta);

	/* Create the array object */
	ret = PyArray_SimpleNewFromData(ndims, dims, dtype->type_num, data);

	/* Attach Leon to the array */
	PyArray_SetBaseObject((PyArrayObject *) ret, (PyObject *) leon);
	return ret;
}

/*
 * Method: SharedArray.CreateArray()
 */
PyObject *shared_array_create(PyObject *self, PyObject *args, PyObject *kwds)
{
	static char *kwlist[] = { "name", "shape", "dtype", NULL };
	const char *name;
	PyArray_Dims shape = { NULL, 0 };
	PyArray_Descr *dtype = NULL;
	PyObject *ret = NULL;

	/* Parse the arguments */
	if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO&|O&", kwlist,
					 &name,
					 PyArray_IntpConverter, &shape,
					 PyArray_DescrConverter, &dtype))
		goto out;

	/* Check the type */
	if (!dtype)
		dtype = PyArray_DescrFromType(NPY_DEFAULT_TYPE);

	/* Now do the real thing */
	ret = do_create(name, shape.len, shape.ptr, dtype);

out:	/* Clean-up on exit */
	if (shape.ptr)
		PyDimMem_FREE(shape.ptr);

	return ret;
}