[Numpy-discussion] "aligned" matrix / ctypes
Zachary Pincus
zachary.pincus@yale....
Thu Apr 24 16:57:22 CDT 2008
Zach:
>> Here's my attempt at aligned_empty(). It only accepts alignments
>> that are
>> an integer multiple (or divisor) of the dtype's itemsize, because of
>> limitations in ndarray.view().
Robert:
> aligned_empty() works for me (after removing the if: suite that guards
> this case) because it correctly .view()s before it slices.
> aligned_empty_arbitrary() doesn't because it slices before it
> .view()s.
As I noted, aligned_empty_arbitrary() does not currently work because
ndarray.view() cannot deal with strided arrays, which (as per another
email thread) I think may be a bug. If it could, then
aligned_empty_arbitrary() would work, and not raise an exception.
However, the truth is that aligned_empty does not work with arbitrary
alignments! If you remove the 'if' guard, various assumptions break,
due to the floor division here:
element_alignment = byte_alignment / dtype.itemsize
which only works right when byte_alignment is an integral multiple of
itemsize.
Otherwise you get:
In [1]: import aligned_allocator
In [2]: a = aligned_allocator.aligned_empty((5,5), float, 3)
In [3]: a[0,:].ctypes.data % 3
Out[3]: 0
In [4]: a[1,:].ctypes.data % 3
Out[4]: 1
In [5]: a[2,:].ctypes.data % 3
Out[5]: 2
Which is to say, the data isn't aligned right.
The reason that one must slice before .view()ing to allow arbitrary
alignment is as follows. Imagine that we want rows of four 2-byte
shorts aligned to 3-byte boundaries. (Assume that we already have a
buffer that starts on a 3-byte boundary.) So we need an array that's 9
bytes wide by however many rows, and then we just want to use the
first eight bytes of row. If we slice first, we can get a strided
array that is eight bytes wide, and thus something that we can
interpret as four shorts. (That is, if .view() could handle strided
arrays.)
On the other hand, there's absolutely no way that we can .view()
before slicing, because our underlying array is 9 bytes wide, and you
can't look at 9 bytes as any integral number of 2-byte shorts.
So .view() should properly fail, and thus we can't get to the slicing.
Fortunately this is all an obtuse corner case, since who ever needs to
align to values that aren't either an integral multiple or divisor of
the itemsize? Nevertheless, anyone who wants to use the
aligned_empty() code should keep the 'if' guard there.
In the mean time, is there any way to (from within python) construct
an array from another array by specifying the dtype and strides? That
is, some other way to do the view/slice business directly?
Thanks,
Zach
More information about the Numpy-discussion
mailing list