defining a variable inside a Defun

Discussion of Common Lisp

defining a variable inside a Defun

Postby joeish80829 » Sun Mar 30, 2014 12:23 am

I'm trying to show the result I'm after by showing the what I don't want. Here is the code I'm referring to, the way the functions work don't matter...I highlight how long it takes to run, them and that is what matters. Just keep an out because 2 functions in my question have names that are exactly the same except for a % at the front of it's name.



Code: Select all
(let ((val nil))
  (defun c-arr-to-vector-float  (a len)
    (cond (val val)
          ((listp a) (progn (setf val (foreign-alloc :float :initial-contents a))
             (%c-arr-to-vector-float val len)))
     (t nil))))


If I run this:
Code: Select all
 (%c-arr-to-vector-float (foreign-alloc :float :initial-contents '(1 2 3)) 3 )


1 million times, it takes 6 seconds. but if define
Code: Select all
(foreign-alloc :float :initial-contents (1 2 3))
first like:
Code: Select all
(defparameter a (foreign-alloc :float :initial-contents '(1 2 3)))


then run
Code: Select all
(%c-arr-to-vector-float a len)
running
Code: Select all
(%c-arr-to-vector-float a len)
only takes .017 seconds...do you see where I'm coming from here...I'm looking to speed up the above function? but each time I run the
Code: Select all
c-arr-to-vector-float function
with the let statement above I have to be able to put in a new value, i.e. every time this is run
Code: Select all
(c-arr-to-vector-float '(1 2 3) 3)
(that's name of the defun in the let) the function should operate on the '(123) and if I give it a '(4 5 6) it should operate on that. And I don't want to make someone run the defparameter first each time, I'm trying to make it be automatic and everything inside one s-expression.
joeish80829
 
Posts: 153
Joined: Tue Sep 03, 2013 5:32 am

Re: defining a variable inside a Defun

Postby nuntius » Sun Mar 30, 2014 9:30 am

It sounds like you are measuring the time to allocate, initialize, and free the "val" parameter a million times.

Is the following what you are looking for?

Code: Select all
(defun test ()
  (let ((arr (foreign-alloc :float :initial-contents '(1 2 3))))
    (dotimes (i 1000000)
      (%c-arr-to-vector-float arr 3))))
User avatar
nuntius
 
Posts: 498
Joined: Sat Aug 09, 2008 10:44 am
Location: Burlington, MA

Re: defining a variable inside a Defun

Postby edgar-rft » Sun Mar 30, 2014 3:46 pm

If I have understood your examples correctly then you want to avoid multiple evaluation of foreign-alloc by caching the old value in a lexical variable.

Code: Select all
(let (old-a val)
  (defun c-arr-to-vector-float (a len)
    (cond ((equal a old-a)  ; a is the same list as in the last call
           (%c-arr-to-vector-float val len))
          ((listp a)   ; a is a list but not the same as in the last call
           (setf old-a a
                 val (foreign-alloc :float :initial-contents a))
           (%c-arr-to-vector-float val len)))
          (t nil))))

The list from a is stored in old-a and the return-value of foreign-alloc is stored in val. If the function is called with a list that is not the same list as the list stored in old-a, then the list from a is stored in old-a, the return-value of foreign-alloc is computed and stored in val. If the function is called with a list that is the same list as the list stored in old-a, the old foreign-alloc return-value from val is used instead.

Caching computed values in a hash-table:

Code: Select all
;; EQUAL is needed here because the key is a list
(defvar hash-table (make-hash-table :test #'equal))

(defun c-arr-to-vector-float (a len)
  (let ((val (gethash a hash-table)))     ; try to get val from hash-table
    (cond (val (%c-arr-to-vector-float val len)) ; use val from hash-table
          ((listp a)
           (setf val (foreign-alloc :float :initial-contents a)
                 (gethash a hash-table) val)     ; store val in hash-table
           (%c-arr-to-vector-float val len))
          (t nil))))

All return-values of foreign-alloc are stored in the hash-table with the list from a as the respective key. If the function is called with a list who's value is not stored in the hash-table the value is computed once and stored in the hash-table. If the function is called with a list who's value is already stored in the hash-table, the value from the hash-table is used instead.

Special care must be taken that the hash-table doesn't grow bigger than the available memory.

- edgar
edgar-rft
 
Posts: 157
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany


Return to Common Lisp

Who is online

Users browsing this forum: No registered users and 3 guests