8000 BUG: define "uint-alignment", fixes complex64 alignment by ahaldane · Pull Request #6377 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: define "uint-alignment", fixes complex64 alignment #6377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Sep 30, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
ENH: Implement methods for uint-alignment
Implements IsAligned, IsUintAligned, npy_uint_alignment
  • Loading branch information
ahaldane committed Sep 27, 2018
commit 27d4ce926b7166c9e7fe88f7b64f8636cb464ee3
17 changes: 17 additions & 0 deletions numpy/core/src/comm 8000 on/array_assign.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,23 @@ raw_array_is_aligned(int ndim, npy_intp *shape,
}
}

NPY_NO_EXPORT int
IsAligned(PyArrayObject *ap)
{
return raw_array_is_aligned(PyArray_NDIM(ap), PyArray_DIMS(ap),
PyArray_DATA(ap), PyArray_STRIDES(ap),
PyArray_DESCR(ap)->alignment);
}

NPY_NO_EXPORT int
IsUintAligned(PyArrayObject *ap)
{
return raw_array_is_aligned(PyArray_NDIM(ap), PyArray_DIMS(ap),
PyArray_DATA(ap), PyArray_STRIDES(ap),
npy_uint_alignment(PyArray_DESCR(ap)->elsize));
}



/* Returns 1 if the arrays have overlapping data, 0 otherwise */
NPY_NO_EXPORT int
Expand Down
14 changes: 14 additions & 0 deletions numpy/core/src/common/array_assign.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@ NPY_NO_EXPORT int
raw_array_is_aligned(int ndim, npy_intp *shape,
char *data, npy_intp *strides, int alignment);

/*
* Checks if an array is aligned to its "true alignment"
* given by dtype->alignment.
*/
NPY_NO_EXPORT int
IsAligned(PyArrayObject *ap);

/*
* Checks if an array is aligned to its "uint alignment"
* given by npy_uint_alignment(dtype->elsize).
*/
NPY_NO_EXPORT int
IsUintAligned(PyArrayObject *ap);

/* Returns 1 if the arrays have overlapping data, 0 otherwise */
NPY_NO_EXPORT int
arrays_overlap(PyArrayObject *arr1, PyArrayObject *arr2);
Expand Down
44 changes: 0 additions & 44 deletions numpy/core/src/multiarray/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,50 +587,6 @@ _zerofill(PyArrayObject *ret)
return 0;
}

NPY_NO_EXPORT int
_IsAligned(PyArrayObject *ap)
{
int i;
npy_uintp aligned;
npy_uintp alignment = PyArray_DESCR(ap)->alignment;

/* alignment 1 types should have a efficient alignment for copy loops */
if (PyArray_ISFLEXIBLE(ap) || PyArray_ISSTRING(ap)) {
npy_intp itemsize = PyArray_ITEMSIZE(ap);
/* power of two sizes may be loaded in larger moves */
if (((itemsize & (itemsize - 1)) == 0)) {
alignment = itemsize > NPY_MAX_COPY_ALIGNMENT ?
NPY_MAX_COPY_ALIGNMENT : itemsize;
}
else {
/* if not power of two it will be accessed bytewise */
alignment = 1;
}
}

if (alignment == 1) {
return 1;
}
aligned = (npy_uintp)PyArray_DATA(ap);

for (i = 0; i < PyArray_NDIM(ap); i++) {
#if NPY_RELAXED_STRIDES_CHECKING
/* skip dim == 1 as it is not required to have stride 0 */
if (PyArray_DIM(ap, i) > 1) {
/* if shape[i] == 1, the stride is never used */
aligned |= (npy_uintp)PyArray_STRIDES(ap)[i];
}
else if (PyArray_DIM(ap, i) == 0) {
/* an array with zero elements is always aligned */
return 1;
}
#else /* not NPY_RELAXED_STRIDES_CHECKING */
aligned |= (npy_uintp)PyArray_STRIDES(ap)[i];
#endif /* not NPY_RELAXED_STRIDES_CHECKING */
}
return npy_is_aligned((void *)aligned, alignment);
}

NPY_NO_EXPORT npy_bool
_IsWriteable(PyArrayObject *ap)
{
Expand Down
44 changes: 41 additions & 3 deletions numpy/core/src/multiarray/common.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#ifndef _NPY_PRIVATE_COMMON_H_
#define _NPY_PRIVATE_COMMON_H_
#include "structmember.h"
#include <numpy/npy_common.h>
#include <numpy/npy_cpu.h>
#include <numpy/ndarraytypes.h>
Expand Down Expand Up @@ -56,9 +57,6 @@ index2ptr(PyArrayObject *mp, npy_intp i);
NPY_NO_EXPORT int
_zerofill(PyArrayObject *ret);

NPY_NO_EXPORT int
_IsAligned(PyArrayObject *ap);

NPY_NO_EXPORT npy_bool
_IsWriteable(PyArrayObject *ap);

Expand Down Expand Up @@ -182,6 +180,15 @@ check_and_adjust_axis(int *axis, int ndim)
return check_and_adjust_axis_msg(axis, ndim, Py_None);
}

/* used for some alignment checks */
#define _ALIGN(type) offsetof(struct {char c; type v;}, v)
/*
* Disable harmless compiler warning "4116: unnamed type definition in
* parentheses" which is caused by the _ALIGN macro.
*/
#if defined(_MSC_VER)
#pragma warning(disable:4116)
#endif

/*
* return true if pointer is aligned to 'alignment'
Expand All @@ -201,6 +208,37 @@ npy_is_aligned(const void * p, const npy_uintp alignment)
}
}

/* Get equivalent "uint" alignment given an itemsize, for use in copy code */
static NPY_INLINE int
npy_uint_alignment(int itemsize)
{
npy_uintp alignment = 0; /* return value of 0 means unaligned */

switch(itemsize){
case 1:
return 1;
case 2:
alignment = _ALIGN(npy_uint16);
break;
case 4:
alignment = _ALIGN(npy_uint32);
break;
case 8:
alignment = _ALIGN(npy_uint64);
break;
case 16:
/*
* 16 byte types are copied using 2 uint64 assignments.
* See the strided copy function in lowlevel_strided_loops.c.
*/
alignment = _ALIGN(npy_uint64);
break;
default:
}

return alignment;
}

/*
* memchr with stride and invert argument
* intended for small searches where a call out to libc memchr is costly.
8000 Expand Down
3 changes: 2 additions & 1 deletion numpy/core/src/multiarray/flagsobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "npy_config.h"

#include "npy_pycompat.h"
#include "array_assign.h"

#include "common.h"

Expand Down Expand Up @@ -64,7 +65,7 @@ PyArray_UpdateFlags(PyArrayObject *ret, int flagmask)
_UpdateContiguousFlags(ret);
}
if (flagmask & NPY_ARRAY_ALIGNED) {
if (_IsAligned(ret)) {
if (IsAligned(ret)) {
PyArray_ENABLEFLAGS(ret, NPY_ARRAY_ALIGNED);
}
else {
Expand Down
11 changes: 0 additions & 11 deletions numpy/core/src/multiarray/lowlevel_strided_loops.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "structmember.h"

#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE
Expand All @@ -20,16 +19,6 @@

#include "lowlevel_strided_loops.h"

/* used for some alignment checks */
#define _ALIGN(type) offsetof(struct {char c; type v;}, v)
/*
* Disable harmless compiler warning "4116: unnamed type definition in
* parentheses" which is caused by the _ALIGN macro.
*/
#if defined(_MSC_VER)
#pragma warning(disable:4116)
#endif


/*
* x86 platform works with unaligned access but the compiler is allowed to
Expand Down
7 changes: 4 additions & 3 deletions numpy/core/src/multiarray/methods.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "conversion_utils.h"
#include "shape.h"
#include "strfuncs.h"
#include "array_assign.h"

#include "methods.h"
#include "alloc.h"
Expand Down Expand Up @@ -1785,11 +1786,11 @@ array_setstate(PyArrayObject *self, PyObject *args)
fa->data = datastr;
#ifndef NPY_PY3K
/* Check that the string is not interned */
if (!_IsAligned(self) || swap || PyString_CHECK_INTERNED(rawdata)) {
if (!IsAligned(self) || swap || PyString_CHECK_INTERNED(rawdata)) {
#else
/* Bytes should always be considered immutable, but we just grab the
* pointer if they are large, to save memory. */
if (!_IsAligned(self) || swap || (len <= 1000)) {
if (!IsAligned(self) || swap || (len <= 1000)) {
#endif
npy_intp num = PyArray_NBYTES(self);
fa->data = PyDataMem_NEW(num);
Expand Down Expand Up @@ -2281,7 +2282,7 @@ array_setflags(PyArrayObject *self, PyObject *args, PyObject *kwds)
if (PyObject_Not(align_flag)) {
PyArray_CLEARFLAGS(self, NPY_ARRAY_ALIGNED);
}
else if (_IsAligned(self)) {
else if (IsAligned(self)) {
PyArray_ENABLEFLAGS(self, NPY_ARRAY_ALIGNED);
}
else {
Expand Down
0