[Numpy-discussion] Request for review: dynamic_cpu_branch

Charles R Harris charlesr.harris at gmail.com
Fri Dec 26 13:00:47 EST 2008


On Fri, Dec 26, 2008 at 10:38 AM, Charles R Harris <
charlesr.harris at gmail.com> wrote:

>
>
> On Fri, Dec 26, 2008 at 2:20 AM, David Cournapeau <cournape at gmail.com>wrote:
>
>> On Fri, Dec 26, 2008 at 4:05 PM, Charles R Harris
>> <charlesr.harris at gmail.com> wrote:
>> >
>> >
>> > On Thu, Dec 25, 2008 at 10:47 PM, David Cournapeau <cournape at gmail.com>
>> > wrote:
>> >>
>> >> On Tue, Dec 23, 2008 at 6:07 PM, Charles R Harris
>> >> <charlesr.harris at gmail.com> wrote:
>> >> >
>> >> >
>> >> > On Mon, Dec 22, 2008 at 11:23 PM, David Cournapeau
>> >> > <david at ar.media.kyoto-u.ac.jp> wrote:
>> >> >>
>> >> >> David Cournapeau wrote:
>> >> >> > Charles R Harris wrote:
>> >> >> >
>> >> >> >> On Mon, Dec 22, 2008 at 10:40 PM, David Cournapeau
>> >> >> >> <cournape at gmail.com
>> >> >> >> <mailto:cournape at gmail.com>> wrote:
>> >> >> >>
>> >> >> >>     On Tue, Dec 23, 2008 at 2:35 PM, Robert Kern
>> >> >> >>     <robert.kern at gmail.com <mailto:robert.kern at gmail.com>>
>> wrote:
>> >> >> >>
>> >> >> >>     >
>> >> >> >>     > I think he meant that it can be discovered at runtime in
>> >> >> >>     general, not
>> >> >> >>     > at numpy-run-time, so we can write a small C program that
>> can
>> >> >> >> be
>> >> >> >> run
>> >> >> >>     > at numpy-build-time to add another entry to config.h.
>> >> >> >>
>> >> >> >>     But then we only move the problem: people who want to build
>> >> >> >> universal
>> >> >> >>     numpy extensions will have the wrong value, no ? The
>> fundamental
>> >> >> >> point
>> >> >> >>     of my patch is that the value is set whenever ndarrayobject.h
>> is
>> >> >> >>     included. So even if I build numpy on PPC, NPY_BIGENDIAN will
>> >> >> >> not
>> >> >> >> be
>> >> >> >>     defined when the header is included for a file build with gcc
>> >> >> >> -arch
>> >> >> >>     i386.
>> >> >> >>
>> >> >> >>
>> >> >> >> We can probably set things up so the determination is at run time
>> --
>> >> >> >> but we need to be sure that the ABI isn't affected. I did that
>> once
>> >> >> >> for an old project that needed data portability. In any case, it
>> >> >> >> sounds like a project for a later release.
>> >> >> >>
>> >> >> >
>> >> >> > It cannot work for numpy without breaking backward compatibility,
>> >> >> > because of the following lines:
>> >> >> >
>> >> >>
>> >> >> Actually, you could, by making the macro point to actual functions,
>> but
>> >> >> that would add function call cost. I don't know if the function call
>> >> >> cost is significant or not in the cases where those macro are used,
>> >> >
>> >> > Exactly. Function calls are pretty cheap on modern hardware with good
>> >> > compilers, nor would I expect the calls to be the bottleneck in most
>> >> > applications. The functions would need to be visible to third party
>> >> > applications, however...
>> >>
>> >> Would it be a problem ? Adding "true" functions to the array api,
>> >> while keeping the macro for backward compatibility should be ok, no ?
>> >
>> > I don't think it's a problem, just that the macros generate code that is
>> > compiled, so they need to call an api function. A decent compiler will
>> > probably load the function pointer somewhere fast if it is called in a
>> loop,
>> > a const keyword somewhere will help with that. We might want something
>> more
>> > convenient for our own code.
>> >
>> >>
>> >> I also updated my patch, with another function PyArray_GetEndianness
>> >> which detects the runtime endianness (using an union int/char[4]). The
>> >> point is to detect any mismatch between the configuration endianness
>> >> and the "true" one, and I put the detection in import_array. The
>> >> function is in the numpy array API, but it does not really need to be
>> >> either .
>> >
>> > That sounds like a good start. It might be a good idea to use something
>> like
>> > npy_int32 instead of a plain old integer. Likewise, it would probably be
>> > good to define the union as an anonymous constant. Hmm...
>> > something like:
>>
>> What I did was a bit more heavyweight, because I added it as function,
>> but the idea is similar:
>>
>> static int compute_endianness()
>> {
>>        union {
>>                char c[4];
>>                npy_uint32 i;
>>        } bint;
>>        int st;
>>
>>        bint.i = 'ABCD';
>>
>>        st = bintstrcmp(bint.c, "ABCD");
>>        if (st == 0) {
>>                return NPY_CPU_BIG;
>>        }
>>        st = bintstrcmp(bint.c, "DCBA");
>>        if (st == 0) {
>>                return NPY_CPU_LITTLE;
>>        }
>>        return NPY_CPU_UNKNOWN_ENDIAN;
>> }
>>
>> Now that I think about it, I don't know if setting an integer to
>> 'ABCD' is legal C. I think it is, but I don't claim to be any kind of
>> C expert.
>
>
> Try
>
>      const  union {
>                char c[4];
>                npy_uint32 i;
>        } bint = {1,2,3,4};
>
> And just compare the resulting value of bint.i to predefined values, i.e.,
> 67305985 for big endian. The
>

Make that little endian.

Chuck
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20081226/aab778e0/attachment.html>


More information about the NumPy-Discussion mailing list