Liam,
I have tried this and (without using (the double-float (...)) since this is unnecessary for cffi:mem-aref with hardcoded :double data type), I get the following timing data:
using the standard grid:gref routine:
Evaluation took:
0.542 seconds of real time
0.536671 seconds of total run time (0.525229 user, 0.011442 system)
[ Run times consist of 0.037 seconds GC time, and 0.500 seconds non-GC time. ]
99.08% CPU
1,189,729,211 processor cycles
153,334,416 bytes consed
using the standard grid:gref* routine:
Evaluation took:
0.067 seconds of real time
0.066006 seconds of total run time (0.063179 user, 0.002827 system)
[ Run times consist of 0.008 seconds GC time, and 0.059 seconds non-GC time. ]
98.51% CPU
146,192,222 processor cycles
27,060,416 bytes consed
using the modified grid:gref* routine (specialized to grid:vector-double-float)
Evaluation took:
0.070 seconds of real time
0.068041 seconds of total run time (0.065151 user, 0.002890 system)
[ Run times consist of 0.011 seconds GC time, and 0.058 seconds non-GC time. ]
97.14% CPU
152,642,611 processor cycles
27,061,456 bytes consed
Apparently my system didn't notice the difference. Also, SBCL complains about the argument (grid::foreign-pointer object) to cffi:mem-aref being of type NUMBER instead of integer or fixnum. Furthermore, it says it has to do float to pointer coercion to <return-value>. I checked that the redefined method is actually used by doing a second run with a print statement added to the defmethod.
using cffi:mem-aref directly:
Evaluation took:
0.002 seconds of real time
0.002483 seconds of total run time (0.002482 user, 0.000001 system)
100.00% CPU
5,442,756 processor cycles
0 bytes consed
I guess that even using compiler macros or other trickery one would have to remove the allocation of linearized indices and foreign ptr addresses from the inner loops as I have done in my example by using auxiliary variables zvector-fptr and output-fptr. Maybe one can define something like
(with-foreign-array (name-of-array :double) ...) that locally redefines (grid:gref name-of-array ...) and (grid:gref* name-of-array ...) as macros evaluating to cffi:mem-aref and storing the respective linearized indices and memory pointers at the level of with-foreign-array? Although not as convenient as some 'self-optimizing' grid:gref, I would consider this a satisfactory solution. Don't know how to do that without getting lost in a forest of commas and backquotes, though.
best regards,
Sebastian
On 27.10.2010, at 05:22, Liam Healy wrote:
> Sebastian,
>
> Can you temporarily define this and find the timing/consing for your
> test case:
>
> (defmethod gref* ((object vector-double-float) linearized-index)
> (cffi:mem-aref
> (foreign-pointer object)
> :double
> linearized-index))
>
> (I think you don't use any matrices but if you do, define an analogous
> function for matrix-double-float.)
>
> As you can see, it has the literal type declaration, and I'm hopeful
> that CFFI will pick that up and make this competitive in speed with
> the best that you saw. If that's so, it should be fairly easy for me
> to make this generic and incorporate it into GSD. I'm still
> interested in making the linearization more efficient if that's still
> significant, but let's try this for now to see how much speed we can
> squeeze out of gref*.
>
> Thanks,
>
> Liam