LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Beating C in Scientific Computing
Applications
Didier Verna
didier@lrde.epita.fr
http://www.lrde.epita.fr/˜didier
Version 1.3 July 2, 2006
1/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Introduction
Myths and legends. . .
Facts:
”LISP is slow” . . . NOT ! (it’s been 20 years)
Image processing libraries written in C or C++
(sacrificing expressiveness for performance)
LISP achieving 60% speed of C
(recent studies)
We have to do better:
Studying behavior and performance of LISP
(part 1: full dedication)
4 simple image processing algorithms
Pixel storage and access / arithmetic operations
Equivalent performance
(LISP 10% better in some cases)
2/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Table of contents
1 Experimental Conditions
2 C Programs and Benchmarks
3 LISP Programs and Benchmarks
4 Type inference
3/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Experimental conditions
The algorithms: the “point-wise” class
Pixel assignment / addition / multiplication / division
Soft parameters: image size / type / storage / access
Hard parameters: compilers / optimization level
More than 1000 individual test cases
The protocol
Debian GNU Linux / 2.4.27-2-686 packaged kernel
Pentium 4 / 3GHz / 1GB RAM / 1MB level 2 cache
Single user mode / SMP off (no hyperthreading)
Measures on 200 consecutive iterations
5/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
C code sample
The add function
void add ( image to , image from , f lo at v a l )
{
i n t i ;
const i n t n = ima>n ;
fo r ( i = 0 ; i < n ; ++ i )
to >data [ i ] = from >data [ i ] + v a l ;
}
Gcc 4.0.3 (Debian package)
Full optimization: -O3 -DNDEBUG plus inlining
Note: inlining should be almost negligible
7/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Results
In terms of behavior
1D implementation slightly better (10% 20%)
Linear access faster (15 35 times)
Arithmetic overhead: only 4x 6x
Main cause: hardware cache optimization
Optimized code faster (60%) in linear case, irrelevant
in pseudo-random access
Causes currently unknown
Inlining negligible (2%)
8/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Results
In terms of performance
Fully optimized inlined C code
Algorithm Integer Image Float Image
Assignment 0.29 0.29
Addition 0.48 0.47
Multiplication 0.48 0.46
Division 0.58 1.93
Not much difference between pixel types
Surprise: integer division should be costly
“Constant Integer Optimization” (with inlining)
Do not neglect inlining !
9/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
LISP code sample
The add function
( defun add ( t o from va l )
( de cl ar e ( t ype ( simplearray s i n g l e f l o at ( ) ) to from ) )
( de cl ar e ( t ype s i n g l e f l o a t va l ) )
( l e t ( ( si z e ( arraydimension to 0 ) ) )
( dotimes ( i s i z e )
( s et f ( a re f t o i ) (+ ( a r ef from i ) va l ) ) ) ) )
CMU-CL (19c), SBCL (0.9.9), ACL (7.0)
Full optimization: (speed 3), 0 elsewhere
Array type: 1D, 2D
Array access: aref, row-major-aref, svref
11/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Comparative results
In terms of behavior
= Plain 2D implementation much slower (2.8x 4.5x)
= Linear access faster (30 times)
Same reasons, same behavior. . .
= Optimized code faster in linear case, irrelevant in
pseudo-random access
= Gain more important in LISP (3x 5x)
= Gain more important on floating point numbers
In LISP, safety is costly
= Inlining negligible
= No “Constant Integer Optimization”
= Negative impact on performance (-15%), if any
Inlining still a “hot” topic (register allocation policies ?)
12/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Comparative results
In terms of performance
Pseudo-random access
Assignment Addition Multiplication Division
0
5
10
15
20
25
30
Execution time (seconds)
Rear to Front: ACL / SBCL / CMU-CL / C
Integer
Floating Point
Assignment: LISP 19% faster than C
Other: insignificant (5%)
Exception: integer division
13/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Comparative results
In terms of performance
Linear access
Assignment Addition Multiplication Division
0
1
2
Execution time (seconds)
Rear to Front: ACL / SBCL / CMU-CL / C
Integer
Floating Point
A CL: poor performance
CMU-CL, SBCL: strictly equivalent to C
C wins on integer division, loses on floating-point one
14/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Type inference
A weakness of COMMON-LISP . . .
Static typing cumbersome (source code annotations)
Can we provide minimal type declarations . . .
. . . and rely on type inference ?
Incremental typing by compilation log examination
Unfortunately:
Compiler messages not necessarily ergonomic
Type inference systems not necessarily clever
16/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Example of (missing) type inference
multiply excerpt
; ; . . .
( de cl ar e ( t ype ( simplearray fixnum ( ) ) to from ) )
( de cl ar e ( t ype fixnum va l ) )
; ; . . .
( s et f ( a re f t o i ) ( the fixnum ( ( ar ef from i ) v a l ) ) ) ) ) )
(
*
fixnum fixnum) = fixnum in general, but. . .
to declared as an array of fixnums,
so the multiplication has to return a fixnum
CMU-CL and SBCL ok, ACL not ok.
Need for further explicit type information
worse in ACL:
declared-fixnums-remain-fixnums-switch
17/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Conclusion
In terms of behavior
External parameters: no surprise
Internal parameters: differences, attenuated by
optimization
In terms of performance
Comparable results in both languages
Very smart LISP compilers (given language
expressiveness)
However:
Typing can be cumbersome
Difficult to provide both correct and minimal information
(weakness of the COMMON-LISP standard)
Inlining is still an issue
18/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Perspectives
Low level: try other compilers / architectures
(and compiler / architecture specific optimization
settings)
Medium level: try more sophisticated algorithms
(neighborhoods, front-propagation)
High level: try different levels of genericity
(dynamic object orientation, static meta-programming)
Do not restrict to image processing
19/20
LISP:
Beating C
Didier Verna
Introduction
Experiments
The case of C
The case of
LISP
Type inference
Conclusion
Quesλ ions ?
Logo by Manfred Spiller
20/20