Presentation is loading. Please wait.

Presentation is loading. Please wait.

11 Speed & Debug.  Lisp is really two languages:  A language for writing fast programs  A language for writing programs fast  In the early stage,

Similar presentations


Presentation on theme: "11 Speed & Debug.  Lisp is really two languages:  A language for writing fast programs  A language for writing programs fast  In the early stage,"— Presentation transcript:

1 11 Speed & Debug

2  Lisp is really two languages:  A language for writing fast programs  A language for writing programs fast  In the early stage, you can trade speed for convenience. Then, you can refine critical portions to make them faster once your program begins to crystallize

3  Optimization  Should be focused on bottlenecks  Should not begin too early  Should begin with algorithms  Programs tend to have a few bottlenecks that account for a great part of the execution time  “Most of the running time in none-IO-bound programs is concentrated in about 3% of the source text. Optimizing these parts of the program will make it run noticeably faster; optimizing the rest of the program will be a waste of time on comparison.”, by Knuth

4  Optimize the program from the top  Make sure that you’re using the most efficient algorithm before you resort to low-level coding tricks  Decisions about algorithms have to be made early

5  Five parameters control the way your code is compiled  Speed: the speed of the code produced by the compiler  Compilation-speed: the speed at which your program will be compiled  Safety: the amount of error-checking done in the object code  Space: the size and memory needs of the object code  Debug: the amount of information retained for debugging

6  The compilation parameters are not real variables. They are assigned weights from 0 (unimportant) to 3 (most important) in declarations  (defun bottlenect (…) (do (…) (…) (do (…) (…) (declare (optimize (speed 3) (safety 0))) …)))  Add such declarations until the code was finished and tested

7  Inline function  Without the cost of calling functions  Similar to macros  Macro ▪ Since macros use mere textual substitution, this may result in unintended side-effects and inefficiency due to re-evaluation of arguments and order of operations ▪ Compiler errors within macros are often difficult to understand, because they refer to the expanded code  Recursive functions cannot be inlined  If an inlined function is redefined, we have to recompile any function that calls it

8  (declaim (inline single?)) (defun single? (lst) (and (consp lst) (null (cdr lst))))  (defun foo (x) (single? (bar x)))  When foo is compiled (defun foo (x) (let ((lst (bar x))) (and (consp lst) (null (cdr lst)))))

9  In most languages, you have to declare the type of each variable, and the variable can only hold values of that type → strongly typed language  Common List uses manifest typing (run-time typing)  Type information is attached to the data objects  Type information is used at run-time  Variables can hold objects of any type  We have to pay for this flexibility in speed ▪ The function have to look at the types of each of its arguments at run- time  If we just want one type, say, fixnum, this is an inefficient way

10  In Common Lisp, type declarations are completely optional  Global declarations are made with declaim  (declaim (type fixnum *count*)) ;type can be omitted  Local declarations are made with declare  (defun poly (a b x) (declare (fixnum a b x)) (+ (* a (expt x 2)) (* b x)))

11  Type declarations are particularly important for the contents of complex objects, including arrays and structures  Declarations can improve efficiency The compiler can determine the types of arguments to functions and represent these objects more efficients ▪ If nothing is known about the type of elements an array will contain, it has to be represented in memory as a block of pointers ▪ If it is known that the array will only contain, say, double- floats, then the array can be represented as a block of actual double-floats

12  (setf x (vector 1.234d0 2.345d0 3.456d0) y (make-array 3 :element-type ‘double-float) (aref y 0) 1.234d0 (aref y 1) 2.345d0 (aref y 2) 3.456d0)

13  (setf a (make-array ‘(1000 1000) :element-type ‘single-float :initial-element 1.0)) (defun sim-elts (a) (declare (type (simple-array single-float (1000 1000)) a)) (let ((sum 0.0)) (declare (type single-float sum)) (dotimes (r 1000) (dotimes (c 1000) (incf sum (aref a r c)))) sum))

14  > (compile-file “..\\test\\declare.lsp”)  > (load “..\\test\\declare.fas”)  > (time (sum-elts a)) Real time: 0.823 sec. Run time: 0.8112052 sec. Space: 11999988 Bytes GC: 1, GC time: 0.1092007 sec. 1000000.0  > (compile-file “..\\test\\nodeclare.lsp”)  > (load “..\\test\\nodeclare.fas”)  > (time (sum-elts-nodeclare a)) Real time: 1.026 sec. Run time: 0.9984064 sec. Space: 11999988 Bytes GC: 2, GC time: 0.2340015 sec. 1000000.0

15  Dynamic allocation is slow  Programs that cons a lot tend to run slowly in Lisp implementations with bad garbage collectors  Until recently, most Lisp implementations have had bad garbage collectors  Efficient programs should cons as little as possible

16  One of the easiest way is to use destructive functions  When you know it’s safe to modify a list, you can use delete instead of remove, nreverse instead of reverse, and so on SAFEDESTRUCTIVE append reverse remove remove-if remove-duplicates subst subst-if union intersection set-difference nconc nreverse delete delete-if delete-duplicates nsubst nsubst-if nunion nintersection nset-difference.

17  Use a pre-allocated vector instead of building it using conses  > (setf *print-array* t) T > (setf vec (make-array 10 :fill-pointer 2 :initial-element nil)) #(NIL NIL) > (length vec) 2 > (vector-push ‘a vec) 2 > vec #(NIL NIL A) > (vector-pop vec) A > vec #(NIL NIL)

18  svref is more efficient than aref  eq is more efficient than eql  (reduce #’+ ‘(1 2 3)) is more efficient than (apply #’+ ‘(1 2 3))

19  trace  (defun count-atoms (expression) (if (atom expression) 1 (+ (count-atoms (first expression)) (count-atoms (rest expresstion)))))  > (count-atoms ‘((this is) (a test))) 7 ;we expect 4

20  > (trace count-atoms) ;; Tracing function COUNT-ATOMS. (COUNT-ATOMS)  (count-atoms '((this is) (a test)))

21 2. Trace: (COUNT-ATOMS '((THIS IS) (A TEST))) 3. Trace: (COUNT-ATOMS '(THIS IS)) 4. Trace: (COUNT-ATOMS 'THIS) 4. Trace: COUNT-ATOMS ==> 1 4. Trace: (COUNT-ATOMS '(IS)) 5. Trace: (COUNT-ATOMS 'IS) 5. Trace: COUNT-ATOMS ==> 1 5. Trace: (COUNT-ATOMS 'NIL) 5. Trace: COUNT-ATOMS ==> 1 4. Trace: COUNT-ATOMS ==> 2 3. Trace: COUNT-ATOMS ==> 3 3. Trace: (COUNT-ATOMS '((A TEST))) 4. Trace: (COUNT-ATOMS '(A TEST)) 5. Trace: (COUNT-ATOMS 'A) 5. Trace: COUNT-ATOMS ==> 1 5. Trace: (COUNT-ATOMS '(TEST)) 6. Trace: (COUNT-ATOMS 'TEST) 6. Trace: COUNT-ATOMS ==> 1 6. Trace: (COUNT-ATOMS 'NIL) 6. Trace: COUNT-ATOMS ==> 1 5. Trace: COUNT-ATOMS ==> 2 4. Trace: COUNT-ATOMS ==> 3 4. Trace: (COUNT-ATOMS 'NIL) 4. Trace: COUNT-ATOMS ==> 1 3. Trace: COUNT-ATOMS ==> 4 2. Trace: COUNT-ATOMS ==> 7 7

22  (defun count-atoms (expression) (cond ((atom expression) 1) ((null expression) 0) (t (+ (count-atoms (first expression)) (count-atoms (rest expression))))))  > (count-atoms ‘((this is) (a test))) 7

23  (defun count-atoms (expression) (cond ((null expression) 0) ((atom expression) 1) (t (+ (count-atoms (first expression)) (count-atoms (rest expression))))))  > (count-atoms ‘((this is) (a test))) 4  > (untrace count-atoms)

24  > (dribble “record.txt”) ; 記錄在 toplevel 的過程 … … > (dribble) ;stop dribbling  > (ed “record.txt”)

25  Write a Lisp program with at least 15 functions  Due June 30  Report  Source code  Demo


Download ppt "11 Speed & Debug.  Lisp is really two languages:  A language for writing fast programs  A language for writing programs fast  In the early stage,"

Similar presentations


Ads by Google