[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

floating point performance



The problem of consing floating point values when calling functions
plagues me.  For instance, inlining just won't help when you're
dealing with generic functions and in general, code is severely
uglified when trying to get maximal performance.  I truly want to be
able to make lisp as fast as C and I think this is possible.

I have a suggestion for making floating point function calls more
efficient.  Why can't the compiler rely on ftype declarations and 
generate code that passes/returns floats on the stack/registers?
Here is the scenario: 

The user declares the type of the function:

(declaim (ftype (function (double-float double-float) double-float) sum+2))

Then, the user declares the function:

(defun sum+2 (x y)
  (declare (type double-float x y)
	   (values double-float))
  (+ (+ x y) 2.0))

Finally, the user declares functions that call the float function, sum+2.

(defun sum*2+2 (x y)
  (declare (type double-float x y)
	   (values double-float))
  (* 2.0 (sum+2 x y)))

Since the compiler has the ftype information for the function, it can
call sum+2 using floats allocated on the stack and expect a return
value in a register or on the stack.

This scenario relies on the fact that (1) the ftype of sum+2 does not
change and (2) the ftype of sum+2 is defined before a function calling
sum+2 is compiled or evaluated.  These restrictions very closely
resemble similar assumptions having to do with defstruct.  In fact on
page 473 of CLtL II, GLS writes:


  X3J13 voted in January 1989 <56> to specify that the results of
  redefining a defstruct structure (that is, evaluating more than one
  defstruct structure for the same name) are undefined.

  The problem is that if instances have been created under the old
  definition then remain accessible after the new definition has been
  evaluated, the accessors and other functions for the new definition
  may be incompatible with the old instances.  Conversely, functions
  associated with the old definition may have been declared inline and
  compiled into code that remains accessible after the new definition
  has been evaluated; such code may be incompatible with the new
  instances. 

  In practice this restriction affects the development and debugging
  process rather than production runs of fully developed code.  The
  defstruct feature is intended to provide "the most efficient"
  structure class.  CLOS classes defined by defclass allow much more
  flexible structures to be defined and redefined.

  Programming environments are allowed and encouraged to permit
  defstruct redefinition, perhaps with warning messages about possible
  interactions with other parts of the programming environment or memory
  state.  It is beyond the scope of the Common Lisp language standard to
  define those interactions except to note that they are not portable.


Obviously, problems will arise if a function call is compiled before
it is defined (with its associated ftype declaration).  Possibly a
remedy is to add a declaration extension (i.e., ftype* or freeze) that
emphasizes the dangerousness of this definition (or at least a flag
that tells the compiler whether or not to take advantage of the ftype
information).

Please let me know what you think!

-- jonathan bachrach (bachrach@psych.stanford.edu)