[Gsll-devel] Recurring callbacks

Liam Healy lhealy at common-lisp.net
Sun Jan 18 17:04:54 UTC 2015


Thanks for your email and patch. I had noticed that integration-qag
appeared to be non-reentrant a couple years ago, and made a little progress
into diagnosing the problem, but didn't get as far as you have. I think
your solution is a good start. As far as callbacks defined through
defmobject, it seems like this could be handled by let binding in the
defmcallback expansion, since they are only ever called in the CBFN
functions. What do you think?

As a side point, it looks like you're trying to do a multivariate integral.
I think you will find the Monte Carlo integration better than nested
calling of univariate integrations for this purpose.

Liam

On Fri, Jan 9, 2015 at 1:37 PM, Eugene Zhemchugov <jini.zh at gmail.com> wrote:

> I was trying to evaluate a recurring integral when I ran into what I
> think a design flaw in the callbacks implementation. Consider the
> following code:
>
> (integration-qag (lambda (x)
>                      (integration-qag (lambda(y)
>                                         (* (sin x) y))
>                                       0d0 1d0 :gauss41))
>                   0d0 pi :gauss41)
>
> The result of the integration should be 1, but I get 4.93. Digging
> through the code, I figured out that callbacks are implemented in the
> following way:
>
> 1. During the GSLL compilation, a callback is defined via the
> CFFI:DEFCALLBACK macro.
> 2. The GSLL wrapper function assigns the function to be called to a
> dynamic variable and calls the underlying GSL function.
> 3. The GSL function calls the CFFI callback.
> 4. The CFFI callback calls the value stored in the dynamic variable.
>
> The relevant part of the GSLL wrapper function is generated by
> BODY-EXPAND. Here is a simplified version of the code generated for
> INTEGRATION-QAG:
>
> (defun integration-qag (function ...)
>    (declare (special integration-qag-dynfn0))
>    (setf integration-qag-dynfn0 function)
>    (foreign-funcall "gsl_integration_qag" ...))
>
> The problem here is that if the function passed as a parameter to the
> GSLL function calls the same GSLL function again, as in the example
> above, the dynamic variable value is overwritten during the second call,
> and then the first GSL function ends up calling the second callback all
> the time. Seemingly, this can be fixed by binding instead of assigning
> the dynamic variable, i.e., by making BODY-EXPAND to generate code like
> this:
>
> (defun integration-qag (function ...)
>    (let ((integration-qag-dynfn0 function))
>      (declare (special integration-qag-dynfn0))
>      (foreign-funcall "gsl_integration_qag" ...)))
>
> In this case the value of INTEGRATION-QAG-DYNFN0 is restored upon
> leaving the LET form. However, having patched the code this way, I broke
> callbacks introduced via the DEFMOBJECT macro. In this case the
> assignment happens in the REINITIALIZE-INSTANCE method specialized on
> this object, which is usually called in the construction phase. As an
> example, consider NONLINEAR-LEAST-SQUARES-EXAMPLE. The assignment is
> made during the call to MAKE-NONLINEAR-FDFFIT, however the callback is
> executed during the call to ITERATE. I think that the binding should be
> performed in ITERATE, as soon as it is needed. ITERATE receives an
> instance of an object subclassed from CALLBACK-INCLUDED, hence it has
> access both to the functions to be called (the FUNCALLABLES slot of
> CALLBACK-INCLUDED) and the callback specification (the CBINFO slot). But
> I don't know what would be the best way to implement it. One possibility
> is to loop through function parameters in BODY-EXPAND and figure out
> which are instances of CALLBACK-INCLUDED. That will work only for
> methods, and only for the specialized parameters. Is it sufficient?
> Other approaches I can think of would require changing the DEFMFUN
> interface to specify which parameters should be used to construct the
> bindings. What solution would you propose? I can make a patch for it if
> you don't think that the changes are too drastic to trust not an
> upstream developer.
>
> You may find my partial patch in the attachement.
>
> _______________________________________________
> Gsll-devel mailing list
> Gsll-devel at common-lisp.net
> http://mailman.common-lisp.net/cgi-bin/mailman/listinfo/gsll-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/gsll-devel/attachments/20150118/955a8069/attachment.html>


More information about the gsll-devel mailing list