David Wingate <[email protected]> writes:

> Hello, all.  I'm trying to bind some BLAS/LAPACK primitives into
> Ikarus to support some machine learning algorithms, and I've got a
> question about best practices.
>
> It's pretty easy to use the FFI to call LAPACK functions.  What I'm
> having trouble with is how to do this the "right" way.
>
> Ultimately, I'd like to be able to write code like the following:
>
> (define a (make-blas-vector 10))  ; create a length 10 vector
> (define b (make-blas-vector 10))
> ; ...populate with data...
> (define c (* (+ a b) 5))   ; <-- this is the important part!
>
> What I do NOT want to have to worry about is the temporary vector
> which is created as a result of calling (+ a b).
>
> That is, under the hood, make-blas-vector is going to malloc() some
> memory, or possibly allocate something via an appropriate FFI
> function.  It's easy to overload the + operator to call a BLAS vector
> adder, and to create a new BLAS vector to store the result of the
> addition.
>
> But I don't want to have to manually free that temporary vector.  When
> it's no longer used / goes out of scope, I want it to be garbage-
> collected.
>
> The problem is that I need to "know" when it's being garbage
> collected, because I need to trigger a low-level free() operation.
>
> So I think that what I want is to create a new native datatype, and
> register appropriate constructors and destructors along with it.
>
> What's the best way to accomplish this (or is my thinking off)?  I've
> poked around, and have not (unsurprisingly) found an easy way to do it
> within user-land ikarus.  My guess is that I'll have to hack something
> more low-level, but I'd like to avoid that if at all possible.
>
Ikarus has `guardians', which allow you to register a group of objects,
and then retrieve them as they are otherwise unreferenced (i.e. ripe for
collection):

(define blas-vector-guardian (make-guardian))

(define (collect-blas-vectors)
  (do ((v (blas-vector-guardian) (blas-vector-guardian)))
      ((not v))
    (free-the-foreign-mem-of-vector v)))

(define (make-blas-vector size)
  (let ((v (construct-blas-vector-via-ffi size)))
    (blas-vector-guardian v)
    v))

Given the above, you have two options to make the reclamation happen
automatically: Either place a call to `collect-blas-vectors' into
`make-blas-vectors', or register `collect-blas-vectors' with the GC,
which is a recently-added feature[0]. You can read more about guardians
in the paper "Guardians in a Generation-Based Garbage Collector", by
Dybvig et al. [1].

[0]
http://thread.gmane.org/gmane.lisp.scheme.ikarus.user/1148/focus=1154
[1] ftp://ftp.cs.indiana.edu/pub/scheme-repository/doc/pubs/guardians.ps.gz


HTH, Rotty
-- 
Andreas Rottmann -- <http://rotty.yi.org/>

Reply via email to