[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