From: <billpeople@mi...>  20111130 09:08:49

Preliminaries  SBCL 1.0.52 beta w/threads for Mac OSX Lion. I've looked through the archives for similar issues, but don't see any. I've inherited an implementation or RK4 (numerical method), where the implementation was copied from a C implementation. It makes extensive use of global variables and it dynamically defines two functions on each pass. The code I inherited does this by generating sexprs that begin (defun rk4_model ...), filling them with the dynamically created code and then calling eval on the resulting sexpr. (EXAMPLES AT END) I'm trying to make this code threadsafe. The problem with the approach outlined above is that the function created is using a globally accessible name, so two separate threads will trash each others definitions. I figured that using (compile NIL '(lambda ...) ) and setting the value of a threadlocal dynamic variable to the resulting compiled function, and using a funcall on the symbol would be equivalent, and threadsafe. However, with no thread involved, I find the results from the original method (eval'ing a defun expr, and calling the result by name) and the new method (compiling a lambda expression and binding the compiled function as a variable value, and using a funcall) to NOT yield the same results. Most obvious is that the original method never yields floating point errors, but the new method often does (at least half of the time). Finally, I don't think this is relevant, but note that the generated code doesn't return useful values, and instead uses the array parameters to transfer results (since the arrays act as a call by reference). (again, examples below) I haven't been able to generate a simpler case to show the issue  the simpler cases all work as they ought, yielding identical results. Thanks. Here's the two different methods of creating the functions: #+COMPILEDLAMBDA (defun rk4preparemodel (model) ;; dynamic variables to bind the results to (declare (special rk4_model_fnc rk4_model_no_diffeq_fnc)) ;; create the model for simulation (multiplevaluebind (rk4model rk4modelnodiffeq) (makerk4model model (buildequations model)) (setf rk4_model_fnc (compile NIL rk4model) rk4_model_no_diffeq_fnc (compile NIL rk4modelnodiffeq)))) #COMPILEDLAMBDA (defun rk4preparemodel (model) ;; create the model for simulation (eval (makerk4model model (buildequations model)))) and here's the different results of makerk4model first the lambda's, then the defun's ((LAMBDA (TIME YARR DYDTARR) (DECLARE (DOUBLEFLOAT TIME) (TYPE (SIMPLEARRAY DOUBLEFLOAT) YARR DYDTARR) (IGNORABLE TIME YARR DYDTARR)) (SETF (AREF *ALGEBRAICVARIABLES* 0) (* (AREF *MODELCONSTANTS* 0) (/ (AREF YARR 0) (+ 1 (* (AREF *MODELCONSTANTS* 4) (AREF YARR 1)) (* (AREF *MODELCONSTANTS* 0) (AREF *MODELCONSTANTS* 5) (AREF YARR 0)))))) (SETF (AREF DYDTARR 0) (* 1 (AREF *ALGEBRAICVARIABLES* 0) (AREF YARR 1))) (SETF (AREF DYDTARR 1) (EQUATIONAGGREGATOR # (* 1 (AREF *MODELCONSTANTS* 6) (AREF YARR 1)) (* (AREF *MODELCONSTANTS* 3) (AREF *ALGEBRAICVARIABLES* 0) (AREF YARR 1))))) (LAMBDA (TIME YARR) (DECLARE (DOUBLEFLOAT TIME) (TYPE (SIMPLEARRAY DOUBLEFLOAT) YARR) (IGNORABLE TIME YARR)) (SETF (AREF *ALGEBRAICVARIABLES* 0) (* (AREF *MODELCONSTANTS* 0) (/ (AREF YARR 0) (+ 1 (* (AREF *MODELCONSTANTS* 4) (AREF YARR 1)) (* (AREF *MODELCONSTANTS* 0) (AREF *MODELCONSTANTS* 5) (AREF YARR 0)))))))) (PROGN (DEFUN RK4_MODEL (TIME YARR DYDTARR) (DECLARE (OPTIMIZE (SPEED 3) (SAFETY 0)) (DOUBLEFLOAT TIME) (TYPE (SIMPLEARRAY DOUBLEFLOAT) YARR DYDTARR) (IGNORABLE TIME YARR DYDTARR)) (SETF (AREF *ALGEBRAICVARIABLES* 0) (* (AREF *MODELCONSTANTS* 0) (/ (AREF YARR 0) (+ 1 (* (AREF *MODELCONSTANTS* 4) (AREF YARR 1)) (* (AREF *MODELCONSTANTS* 0) (AREF *MODELCONSTANTS* 5) (AREF YARR 0)))))) (SETF (AREF DYDTARR 0) (* 1 (AREF *ALGEBRAICVARIABLES* 0) (AREF YARR 1))) (SETF (AREF DYDTARR 1) (EQUATIONAGGREGATOR # (* 1 (AREF *MODELCONSTANTS* 6) (AREF YARR 1)) (* (AREF *MODELCONSTANTS* 3) (AREF *ALGEBRAICVARIABLES* 0) (AREF YARR 1))))) (DEFUN RK4_MODEL_NO_DIFFEQ (TIME YARR) (DECLARE (OPTIMIZE (SPEED 3) (SAFETY 0)) (DOUBLEFLOAT TIME) (TYPE (SIMPLEARRAY DOUBLEFLOAT) YARR) (IGNORABLE TIME YARR)) (SETF (AREF *ALGEBRAICVARIABLES* 0) (* (AREF *MODELCONSTANTS* 0) (/ (AREF YARR 0) (+ 1 (* (AREF *MODELCONSTANTS* 4) (AREF YARR 1)) (* (AREF *MODELCONSTANTS* 0) (AREF *MODELCONSTANTS* 5) (AREF YARR 0)))))))) 