Commit 69c47167 authored by Mat's avatar Mat
Browse files

Return page aligned arrays

Some libraries that use SIMD instructions require numpy arrays to be
aligned in memory. This is the case for instance with fftw. By moving
the meta-data structure to the end of the shared memory file the
arrays are now naturally page aligned, as returned by mmap().
parent 24fa33b3
Loading
Loading
Loading
Loading
+13 −10
Original line number Diff line number Diff line
@@ -34,9 +34,9 @@
static PyObject *do_attach(const char *name)
{
	struct array_meta meta;
	void *data;
	int fd;
	size_t map_size;
	void *map_addr;
	PyObject *ret;
	PyLeonObject *leon;

@@ -44,6 +44,12 @@ static PyObject *do_attach(const char *name)
	if ((fd = shm_open(name, O_RDWR, 0)) < 0)
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);

	/* Seek to the meta data location */
	if (lseek(fd, -sizeof (meta), SEEK_END) < 0) {
		close(fd);
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
	}

	/* Read the meta data structure */
	if (read(fd, &meta, sizeof (meta)) != sizeof (meta)) {
		close(fd);
@@ -53,16 +59,14 @@ static PyObject *do_attach(const char *name)
	/* Check the meta data */
	if (strncmp(meta.magic, SHARED_ARRAY_MAGIC, sizeof (meta.magic))) {
		close(fd);
		PyErr_SetString(PyExc_IOError,
				"No SharedArray at this address");
		PyErr_SetString(PyExc_IOError, "No SharedArray at this address");
		return NULL;
	}

	/* Check the number of dimensions */
	if (meta.ndims > SHARED_ARRAY_NDIMS_MAX) {
		close(fd);
		PyErr_SetString(PyExc_ValueError,
				"Too many dimensions, recompile SharedArray!");
		PyErr_SetString(PyExc_ValueError, "Too many dimensions, recompile SharedArray!");
		return NULL;
	}

@@ -70,20 +74,19 @@ static PyObject *do_attach(const char *name)
	map_size = meta.size + sizeof (meta);

	/* Map the array data */
	data = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	map_addr = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	close(fd);
	if (data == MAP_FAILED)
	if (map_addr == MAP_FAILED)
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);

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

	/* Create the array object */
	ret = PyArray_SimpleNewFromData(meta.ndims, meta.dims, meta.typenum,
					data + sizeof (meta));
	ret = PyArray_SimpleNewFromData(meta.ndims, meta.dims, meta.typenum, map_addr);

	/* Attach Leon to the array */
	PyArray_SetBaseObject((PyArrayObject *) ret, (PyObject *) leon);
+9 −11
Original line number Diff line number Diff line
@@ -34,9 +34,9 @@
static PyObject *do_create(const char *name, int ndims, npy_intp *dims, PyArray_Descr *dtype)
{
	struct array_meta *meta;
	void *data;
	size_t size;
	size_t map_size;
	void *map_addr;
	int i;
	int fd;
	PyObject *ret;
@@ -44,8 +44,7 @@ static PyObject *do_create(const char *name, int ndims, npy_intp *dims, PyArray_

	/* Check the number of dimensions */
	if (ndims > SHARED_ARRAY_NDIMS_MAX) {
		PyErr_SetString(PyExc_ValueError,
				"Too many dimensions, recompile SharedArray!");
		PyErr_SetString(PyExc_ValueError, "Too many dimensions, recompile SharedArray!");
		return NULL;
	}

@@ -61,20 +60,20 @@ static PyObject *do_create(const char *name, int ndims, npy_intp *dims, PyArray_
	if ((fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0)
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);

	/* Set the block size */
	/* Grow the file */
	if (ftruncate(fd, map_size) < 0) {
		close(fd);
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
	}

	/* Map it */
	data = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	map_addr = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	close(fd);
	if (data == MAP_FAILED)
	if (map_addr == MAP_FAILED)
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);

	/* Build the meta-data structure in memory */
	meta = (struct array_meta *) data;
	/* Append meta-data to the array in memory */
	meta = (struct array_meta *) (map_addr + size);
	strncpy(meta->magic, SHARED_ARRAY_MAGIC, sizeof (meta->magic));
	meta->size = size;
	meta->typenum = dtype->type_num;
@@ -85,12 +84,11 @@ static PyObject *do_create(const char *name, int ndims, npy_intp *dims, PyArray_
	/* Summon Leon to cleanup later */
	leon = PyObject_MALLOC(sizeof (*leon));
	PyObject_INIT((PyObject *) leon, &PyLeonObject_Type);
	leon->data = data;
	leon->data = map_addr;
	leon->size = map_size;

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

	/* Attach Leon to the array */
	PyArray_SetBaseObject((PyArrayObject *) ret, (PyObject *) leon);
+6 −0
Original line number Diff line number Diff line
@@ -40,6 +40,12 @@ static PyObject *do_delete(const char *name)
	if ((fd = shm_open(name, O_RDWR, 0)) < 0)
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);

	/* Seek to the meta data location */
	if (lseek(fd, -sizeof (meta), SEEK_END) < 0) {
		close(fd);
		return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
	}

	/* Read the meta data structure */
	size = read(fd, &meta, sizeof (meta));
	close(fd);
+6 −0
Original line number Diff line number Diff line
@@ -61,6 +61,12 @@ static int get_meta(const struct dirent *dirent, struct array_meta *meta)
	if ((fd = open(path, O_RDONLY, 0666)) < 0)
		return -1;

	/* Seek to the meta data location */
	if (lseek(fd, -sizeof (*meta), SEEK_END) < 0) {
		close(fd);
		return -1;
	}

	/* Read the meta data structure */
	if (read(fd, meta, sizeof (*meta)) != sizeof (*meta)) {
		close(fd);