Building a linux/Pi library to call via FFI

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
29 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] MadgwickAHRS plugin and support code (was: Building a linux/Pi library to call via FFI)

timrowledge

On 12-09-2015, at 6:47 PM, David T. Lewis <[hidden email]> wrote:
> I don't know what got into me, but I brewed up a nice pot of coffee this
> morning and ended up with http://squeaksource.com/MadgwickAHRS/
>
> This is a plugin, accessor class, and unit tests that claim to demonstrate
> that the plugin works.
>
> I used FloatArray for parameter passing, on the theory that users of the
> plugin may be doing float (not double) arithmetic, so it may be more
> efficient to pass values in that manner.

Cool! I did actually write one as well, but I used an array of BoxedFloat64 (or whatever it is) for input and create a 4 element array for the quaternion result. I considered a FloatArray as well but
a) I’ve never used one before, so I’m scared of them
b) Won’t they be arrays of 64bit float values on a 64-bit image?
c) I’m pretty sure I will have to create a bunch of floats when reading the IMU chip anyway, so since I have them, might at well stick’em in an array.

I did consider making the array 13 long so the result could be just appended. Might be worth trying?

The good news is that on a Pi 2 the call as-is costs ~8micro-sec, which considering it apparently uses ~50 +, 60 -, 150 *, 14 / and 5 sqrt floating point calls is quite impressive.

And yes, I suppose we’ll need to keep this as an external plugin to dodge the gnu-stasi. Sigh.


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Oxymorons: Same difference



Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] MadgwickAHRS plugin and support code (was: Building a linux/Pi library to call via FFI)

David T. Lewis
On Sat, Sep 12, 2015 at 08:49:50PM -0700, tim Rowledge wrote:

>
> On 12-09-2015, at 6:47 PM, David T. Lewis <[hidden email]> wrote:
> > I don't know what got into me, but I brewed up a nice pot of coffee this
> > morning and ended up with http://squeaksource.com/MadgwickAHRS/
> >
> > This is a plugin, accessor class, and unit tests that claim to demonstrate
> > that the plugin works.
> >
> > I used FloatArray for parameter passing, on the theory that users of the
> > plugin may be doing float (not double) arithmetic, so it may be more
> > efficient to pass values in that manner.
>
> Cool! I did actually write one as well, but I used an array of BoxedFloat64 (or whatever it is) for input and create a 4 element array for the quaternion result. I considered a FloatArray as well but
> a) I?ve never used one before, so I?m scared of them

Well it's basically the only convenient way to deal with float (as opposed
to double) floating point values. In Squeak, a Float is a C double, and
AFIK the only thing that directly represents single precision floats is
FloatArray. You would be justified in being scared of them, especially
if any of this sounds like it makes sense. But it does work and it might
be more efficient than arrays of Float (C doubles). Or maybe not, I don't
have any way to measure it. But I tried to set things up so that the
FloatArray things can be reused to avoid allocations and type conversions,
so maybe it will help.

> b) Won?t they be arrays of 64bit float values on a 64-bit image?

On the 64 bit V3 image, no. For 64 bit Spur, I am not sure. But by definition
I would expect FloatArray to contain single precision float values in any
image format, so there is a good chance that it will work on 64 bit Spur
also. I did test on 64 bit V3, and that passes the unit tests.

> c) I?m pretty sure I will have to create a bunch of floats when reading the IMU chip anyway, so since I have them, might at well stick?em in an array.
>

I was mainly thinking of matching the parameters to MadgwickAHRSupdate(),
which are single precision float. I don't know anything about IMU chips,
so I don't have a clue if that is a good fit. And I had to look up "IMU"
on Google, so that should give you an idea of my level of expertise.

> I did consider making the array 13 long so the result could be just appended. Might be worth trying?
>

That would work also. I don't think there would be a performance difference
either way, so whichever is easier to understand and document is probably good.
 
> The good news is that on a Pi 2 the call as-is costs ~8micro-sec, which considering it apparently uses ~50 +, 60 -, 150 *, 14 / and 5 sqrt floating point calls is quite impressive.
>
> And yes, I suppose we?ll need to keep this as an external plugin to dodge the gnu-stasi. Sigh.
>

Building external is easy, not an issue. But I think we need to keep the GPL
source code out of the platforms/Cross tree to prevent license confusion, so
that means linking to an installed library rather than linking the GPL code
directly into the plugin. That should not be a problem but I have not actually
done it yet.

Dave


Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] MadgwickAHRS plugin and support code

Herbert König
Hi,

Am 13.09.2015 um 06:31 schrieb David T. Lewis:
> Well it's basically the only convenient way to deal with float (as
> opposed to double) floating point values. In Squeak, a Float is a C
> double, and AFIK the only thing that directly represents single
> precision floats is FloatArray. You would be justified in being scared
> of them, especially if any of this sounds like it makes sense. But it
> does work and it might be more efficient than arrays of Float (C
> doubles). Or maybe not, I don't have any way to measure it. But I
> tried to set things up so that the FloatArray things can be reused to
> avoid allocations and type conversions, so maybe it will help.

FloatArray offers a lot of speed up as long as the operations provided
by Float array are sufficient. Getting Squeak Floats into and out of
Float Array is expensive.
This:
Time millisecondsToRun:
     [|array1 array2|
     array1 := (1.0 to: 10000.0 by: 0.1) asArray.
     array2 := (10000.0 to: 1.0 by: -0.1) asArray.
     1000 timesRepeat: [|result|
         result := array1  * array2]]
22 seconds
is not much slower than using FloatArray
Time millisecondsToRun:
     [|array1 array2|
     array1 := (1.0 to: 10000.0 by: 0.1) asArray.
     array2 := (10000.0 to: 1.0 by: -0.1) asArray.
     1000 timesRepeat: [|result|
         result := (array1 asFloatArray * array2 asFloatArray)]]
19 seconds
If you change the last line to use more operations supported by
FloatArray like:
         result := (array1 asFloatArray * array2 asFloatArray + 7.0 *
3.0) sum
with FloatArrays you get the same speed, without the conversion to
FloatArray it takes three times as long.

If you need to use FloatArray>>at: and #at:put very often FloatArrays
may get slower than Arrays of Float.
So benchmark and benchmark again.

And if your values get small, FloatArray may round them to zero which is
bad for division.

I used FloatArray a lot for  Audio processing and neural networks but
they need to be handled with care.
I ended up using both depending on the algorithm.

Cheers,

Herbert



Reply | Threaded
Open this post in threaded view
|

Re: MadgwickAHRS plugin and support code (was: Building a linux/Pi library to call via FFI)

Ben Coman
In reply to this post by David T. Lewis
On Sun, Sep 13, 2015 at 9:47 AM, David T. Lewis <[hidden email]> wrote:

> On Thu, Sep 10, 2015 at 10:29:24AM -0700, tim Rowledge wrote:
>>
>> On 09-09-2015, at 6:53 PM, David T. Lewis <[hidden email]> wrote:
>>
>> > On Wed, Sep 09, 2015 at 11:17:08AM -0700, tim Rowledge wrote:
>> >> I?m trying - and so far failing - to do what should surely be a very simple
>> >> thing. This isn?t a new situation?  especially on unix.
>> >>
>> >> I have a single C file with just two functions. I have a matching H file.
>> >> I want to make them into a dynamic library that I can call via FFI. This
>> >> really shouldn?t be rocket science stuff!
>> >
>> > <OT>
>> > I assume there is some good reason that you would not do an end run
>> > around all that rocket science and just write a plugin?
>>
>> Well I *did* originally point out that there was probably a really stupid mistake in my process and that is pretty much it. In my defence I was in the midst of FFI-ing to multiple external libraries for assorted Pi add-on doohickeys and getting somewhat inured to the idea.
>>
>> But I think I may re-do it as a plugin today, not least because it seems that the ARM ffi interface has a problem with returning floats; they come back as Character null. I may not be a great IEEE floating point standard expert but that doesn?t seem quite right.
>>
>
> I don't know what got into me, but I brewed up a nice pot of coffee this
> morning and ended up with http://squeaksource.com/MadgwickAHRS/
>
> This is a plugin, accessor class, and unit tests that claim to demonstrate
> that the plugin works.
>
> I used FloatArray for parameter passing, on the theory that users of the
> plugin may be doing float (not double) arithmetic, so it may be more
> efficient to pass values in that manner.
>
> It works with 32/64 bit image and host, and the plugin builds without complaint
> (trunk with Ian's Cmake build) if you put the library source files
> MadgwickAHRS.c and MadgwickAHRS.h in platforms/Cross/plugins/MadgwickAHRS/
>
> The MadgwickAHRS library is licensed GPL, so it would be best to link
> the plugin dynamically to e.g. /usr/local/iib/libwmadgwickIMU.so.1
> rather than static link to the C code as I have done so far.

Unfortunately the distinction you make between static and dynamic
linking is incorrect for GPL code [1][2], and true only for LGPL code.

Now I notice that although [3] indicates the license is GPL, [3]
points to original post [4] which was LGPL.   A little confusing since
neither [3] nor [4] state a license in the C source files.  It seems
[4] is the same author, so maybe its worth a polite query as to why
the license changed from LGPL to GPL.

[1] http://www.gnu.org/licenses/gpl-faq.html#GPLStaticVsDynamic
[2] http://www.dwheeler.com/essays/floss-license-slide.html
[3] http://www.x-io.co.uk/open-source-imu-and-ahrs-algorithms/
[4] https://code.google.com/p/imumargalgorithm30042010sohm/

cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] MadgwickAHRS plugin and support code (was: Building a linux/Pi library to call via FFI)

timrowledge
In reply to this post by David T. Lewis

On 13-09-2015, at 8:26 AM, Ben Coman <[hidden email]> wrote:

> Unfortunately the distinction you make between static and dynamic
> linking is incorrect for GPL code [1][2], and true only for LGPL code.
>
> Now I notice that although [3] indicates the license is GPL, [3]
> points to original post [4] which was LGPL.   A little confusing since
> neither [3] nor [4] state a license in the C source files.  It seems
> [4] is the same author, so maybe its worth a polite query as to why
> the license changed from LGPL to GPL.
>
> [1] http://www.gnu.org/licenses/gpl-faq.html#GPLStaticVsDynamic
> [2] http://www.dwheeler.com/essays/floss-license-slide.html
> [3] http://www.x-io.co.uk/open-source-imu-and-ahrs-algorithms/
> [4] https://code.google.com/p/imumargalgorithm30042010sohm/

Ah, this brings back memories of arguing license for month after month….

To further confuse things, the madgwick code isn’t released as a library but rather just as some code to include in your own system. And the page for the c++ (hack, spit) version shows it as creative commons share-alike 3.0

And as an extra bit of excitement, I spotted a webpage where some corrections to the algorithm were mentioned along with a claim that the x-io site copies would be soon updated. Dating back at least a couple of years...


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Useful random insult:- If his IQ was two points higher he'd be a rock.



Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] MadgwickAHRS plugin and support code

David T. Lewis
In reply to this post by Herbert König
On Sun, Sep 13, 2015 at 01:34:32PM +0200, Herbert K??nig wrote:

> Hi,
>
> Am 13.09.2015 um 06:31 schrieb David T. Lewis:
> >Well it's basically the only convenient way to deal with float (as
> >opposed to double) floating point values. In Squeak, a Float is a C
> >double, and AFIK the only thing that directly represents single
> >precision floats is FloatArray. You would be justified in being scared
> >of them, especially if any of this sounds like it makes sense. But it
> >does work and it might be more efficient than arrays of Float (C
> >doubles). Or maybe not, I don't have any way to measure it. But I
> >tried to set things up so that the FloatArray things can be reused to
> >avoid allocations and type conversions, so maybe it will help.
>
> FloatArray offers a lot of speed up as long as the operations provided
> by Float array are sufficient. Getting Squeak Floats into and out of
> Float Array is expensive.
> This:
> Time millisecondsToRun:
>     [|array1 array2|
>     array1 := (1.0 to: 10000.0 by: 0.1) asArray.
>     array2 := (10000.0 to: 1.0 by: -0.1) asArray.
>     1000 timesRepeat: [|result|
>         result := array1  * array2]]
> 22 seconds
> is not much slower than using FloatArray
> Time millisecondsToRun:
>     [|array1 array2|
>     array1 := (1.0 to: 10000.0 by: 0.1) asArray.
>     array2 := (10000.0 to: 1.0 by: -0.1) asArray.
>     1000 timesRepeat: [|result|
>         result := (array1 asFloatArray * array2 asFloatArray)]]
> 19 seconds
> If you change the last line to use more operations supported by
> FloatArray like:
>         result := (array1 asFloatArray * array2 asFloatArray + 7.0 *
> 3.0) sum
> with FloatArrays you get the same speed, without the conversion to
> FloatArray it takes three times as long.
>
> If you need to use FloatArray>>at: and #at:put very often FloatArrays
> may get slower than Arrays of Float.
> So benchmark and benchmark again.
>
> And if your values get small, FloatArray may round them to zero which is
> bad for division.
>
> I used FloatArray a lot for  Audio processing and neural networks but
> they need to be handled with care.
> I ended up using both depending on the algorithm.

Herbert,

Thanks, that is good to know. Indeed it might be faster to just use arrays
of Float, and it might be worth trying both ways to see which is better.

Dave

 

Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] MadgwickAHRS plugin and support code

Eliot Miranda-2
In reply to this post by Herbert König
Hi Herbert,

On Sun, Sep 13, 2015 at 4:34 AM, Herbert König <[hidden email]> wrote:
Hi,

Am 13.09.2015 um 06:31 schrieb David T. Lewis:
Well it's basically the only convenient way to deal with float (as opposed to double) floating point values. In Squeak, a Float is a C double, and AFIK the only thing that directly represents single precision floats is FloatArray. You would be justified in being scared of them, especially if any of this sounds like it makes sense. But it does work and it might be more efficient than arrays of Float (C doubles). Or maybe not, I don't have any way to measure it. But I tried to set things up so that the FloatArray things can be reused to avoid allocations and type conversions, so maybe it will help.

FloatArray offers a lot of speed up as long as the operations provided by Float array are sufficient. Getting Squeak Floats into and out of Float Array is expensive.
This:
Time millisecondsToRun:
    [|array1 array2|
    array1 := (1.0 to: 10000.0 by: 0.1) asArray.
    array2 := (10000.0 to: 1.0 by: -0.1) asArray.
    1000 timesRepeat: [|result|
        result := array1  * array2]]
22 seconds
is not much slower than using FloatArray
Time millisecondsToRun:
    [|array1 array2|
    array1 := (1.0 to: 10000.0 by: 0.1) asArray.
    array2 := (10000.0 to: 1.0 by: -0.1) asArray.
    1000 timesRepeat: [|result|
        result := (array1 asFloatArray * array2 asFloatArray)]]
19 seconds
If you change the last line to use more operations supported by FloatArray like:
        result := (array1 asFloatArray * array2 asFloatArray + 7.0 * 3.0) sum
with FloatArrays you get the same speed, without the conversion to FloatArray it takes three times as long.

If you need to use FloatArray>>at: and #at:put very often FloatArrays may get slower than Arrays of Float.
So benchmark and benchmark again.

That's right.  Using FloatArray implies an object allocation on every at:, to construct the (boxed) Float result.  64-bit Spur will change this equation because most of the time the floats fetched will be immediate, instances of SmallFloat64.  And indeed they may make it attractive to have a 64-bit float array type.


And if your values get small, FloatArray may round them to zero which is bad for division.

I used FloatArray a lot for  Audio processing and neural networks but they need to be handled with care.
I ended up using both depending on the algorithm.

Cheers,

Herbert






--
_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] MadgwickAHRS plugin and support code

Levente Uzonyi-2
We might as well have primitives which write their result into an object
passed as parameter, or primitives which update the receiver, like the
ones provided by KedamaFloatArray. But with SmallFloat64 being on the way,
it's not that tempting to write such primitives.

Levente

On Mon, 14 Sep 2015, Eliot Miranda wrote:

> Hi Herbert,
>
> On Sun, Sep 13, 2015 at 4:34 AM, Herbert König <[hidden email]> wrote:
>       Hi,
>
>       Am 13.09.2015 um 06:31 schrieb David T. Lewis:
>             Well it's basically the only convenient way to deal with float (as opposed to double) floating point values. In Squeak, a
>             Float is a C double, and AFIK the only thing that directly represents single precision floats is FloatArray. You would be
>             justified in being scared of them, especially if any of this sounds like it makes sense. But it does work and it might be
>             more efficient than arrays of Float (C doubles). Or maybe not, I don't have any way to measure it. But I tried to set
>             things up so that the FloatArray things can be reused to avoid allocations and type conversions, so maybe it will help.
>
>
>       FloatArray offers a lot of speed up as long as the operations provided by Float array are sufficient. Getting Squeak Floats into and
>       out of Float Array is expensive.
>       This:
>       Time millisecondsToRun:
>           [|array1 array2|
>           array1 := (1.0 to: 10000.0 by: 0.1) asArray.
>           array2 := (10000.0 to: 1.0 by: -0.1) asArray.
>           1000 timesRepeat: [|result|
>               result := array1  * array2]]
>       22 seconds
>       is not much slower than using FloatArray
>       Time millisecondsToRun:
>           [|array1 array2|
>           array1 := (1.0 to: 10000.0 by: 0.1) asArray.
>           array2 := (10000.0 to: 1.0 by: -0.1) asArray.
>           1000 timesRepeat: [|result|
>               result := (array1 asFloatArray * array2 asFloatArray)]]
>       19 seconds
>       If you change the last line to use more operations supported by FloatArray like:
>               result := (array1 asFloatArray * array2 asFloatArray + 7.0 * 3.0) sum
>       with FloatArrays you get the same speed, without the conversion to FloatArray it takes three times as long.
>
>       If you need to use FloatArray>>at: and #at:put very often FloatArrays may get slower than Arrays of Float.
>       So benchmark and benchmark again.
>
>
> That's right.  Using FloatArray implies an object allocation on every at:, to construct the (boxed) Float result.  64-bit Spur will change this
> equation because most of the time the floats fetched will be immediate, instances of SmallFloat64.  And indeed they may make it attractive to have
> a 64-bit float array type.
>
>
>       And if your values get small, FloatArray may round them to zero which is bad for division.
>
>       I used FloatArray a lot for  Audio processing and neural networks but they need to be handled with care.
>       I ended up using both depending on the algorithm.
>
>       Cheers,
>
>       Herbert
>
>
>
>
>
>
> --
> _,,,^..^,,,_
> best, Eliot
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] MadgwickAHRS plugin and support code

David T. Lewis
On Mon, Sep 14, 2015 at 11:33:35PM +0200, Levente Uzonyi wrote:
> We might as well have primitives which write their result into an object
> passed as parameter, or primitives which update the receiver, like the
> ones provided by KedamaFloatArray. But with SmallFloat64 being on the way,
> it's not that tempting to write such primitives.
>
> Levente

Actually, that is exactly what I did. The caller provides a pre-allocated
(and potentially reusable) FloatArray of size 4, and the primitive copies
four result values into the array fields. There is no need for allocating
Float objects within the primitive, and no need to convert float to double
in the primitive. This may or may not be useful depending on how the
primitive is used, but it does allow the user an opportunity to optimize
both by reusing an existing FloatArray instance for the results, and by
allocating new Float object only if and when the elements of that array
are actually read and used.

I would expect that FloatArray will still have 32-bit float values in
a 64-bit object memory, after all that is what it was designed to do.
The need to allocate Float objects and do conversion from single to
double floats should go away with 64-bits, so that should be a win.
I expect that updates for MadgwickAHRSPlugin should be minimal.

Dave


>
> On Mon, 14 Sep 2015, Eliot Miranda wrote:
>
> >Hi Herbert,
> >
> >On Sun, Sep 13, 2015 at 4:34 AM, Herbert K??nig <[hidden email]>
> >wrote:
> >      Hi,
> >
> >      Am 13.09.2015 um 06:31 schrieb David T. Lewis:
> >            Well it's basically the only convenient way to deal with float
> >            (as opposed to double) floating point values. In Squeak, a
> >            Float is a C double, and AFIK the only thing that directly
> >            represents single precision floats is FloatArray. You would be
> >            justified in being scared of them, especially if any of this
> >            sounds like it makes sense. But it does work and it might be
> >            more efficient than arrays of Float (C doubles). Or maybe not,
> >            I don't have any way to measure it. But I tried to set
> >            things up so that the FloatArray things can be reused to avoid
> >            allocations and type conversions, so maybe it will help.
> >
> >
> >      FloatArray offers a lot of speed up as long as the operations
> >      provided by Float array are sufficient. Getting Squeak Floats into
> >      and
> >      out of Float Array is expensive.
> >      This:
> >      Time millisecondsToRun:
> >      ?? ?? [|array1 array2|
> >      ?? ?? array1 := (1.0 to: 10000.0 by: 0.1) asArray.
> >      ?? ?? array2 := (10000.0 to: 1.0 by: -0.1) asArray.
> >      ?? ?? 1000 timesRepeat: [|result|
> >      ?? ?? ?? ?? result := array1?? * array2]]
> >      22 seconds
> >      is not much slower than using FloatArray
> >      Time millisecondsToRun:
> >      ?? ?? [|array1 array2|
> >      ?? ?? array1 := (1.0 to: 10000.0 by: 0.1) asArray.
> >      ?? ?? array2 := (10000.0 to: 1.0 by: -0.1) asArray.
> >      ?? ?? 1000 timesRepeat: [|result|
> >      ?? ?? ?? ?? result := (array1 asFloatArray * array2 asFloatArray)]]
> >      19 seconds
> >      If you change the last line to use more operations supported by
> >      FloatArray like:
> >      ?? ?? ?? ?? result := (array1 asFloatArray * array2 asFloatArray +
> >      7.0 * 3.0) sum
> >      with FloatArrays you get the same speed, without the conversion to
> >      FloatArray it takes three times as long.
> >
> >      If you need to use FloatArray>>at: and #at:put very often
> >      FloatArrays may get slower than Arrays of Float.
> >      So benchmark and benchmark again.
> >
> >
> >That's right.?? Using FloatArray implies an object allocation on every
> >at:, to construct the (boxed) Float result. ??64-bit Spur will change this
> >equation because most of the time the floats fetched will be immediate,
> >instances of SmallFloat64.?? And indeed they may make it attractive to have
> >a 64-bit float array type.
> >
> >
> >      And if your values get small, FloatArray may round them to zero
> >      which is bad for division.
> >
> >      I used FloatArray a lot for?? Audio processing and neural networks
> >      but they need to be handled with care.
> >      I ended up using both depending on the algorithm.
> >
> >      Cheers,
> >
> >      Herbert
> >
> >
> >
> >
> >
> >
> >--
> >_,,,^..^,,,_
> >best,??Eliot
> >
> >

>


12