[I added some more people to the CC]
Akshay Srinivasan akshaysrinivasan@gmail.com writes:
At Thu, 07 Mar 2013 10:35:46 +0100, Nicolas Neuss wrote:
Akshay Srinivasan akshaysrinivasan@gmail.com writes:
I wanted to polish the whole "static object" thing I'm doing write now, by writing a thin layer over defclass itself. This seems awful lot like MOP.
What I'm doing right now is essentially that every tensor class has a set of inlined functions associated with it, which are then used inside macros everywhere to define type specific functions.
From what I understand of MOP, I can possibly define a meta-class which holds all these functions, and then possibly define the defmethod over instances of the metaclass (which sort of does the equivalent of macroexpansion ?). Essentially I don't really want to have runtime dispatch; can I define in some sense a meta-version of defmethod/defgeneric on a class so that it wraps the code for the method inside a symbol-macrolet to replace things like "+,-" with something specialised for the class?
Although I already can imagine what you want quite well - could you maybe sketch an example (as simple as possible)?
I can't find any real resource on MOP, so forgive me if this doesn't make any sense whatsoever.
The chapters 5 and 6 of the AMOP book should be freely available, see
http://www.clisp.org/impnotes/mop-chap.html
or google for "mop_spec.pdf".
Nicholas: I know this is probably more up your alley. Do you think this sort of thing is possible with MOP ?
I doubt a little that the MOP is sufficient for achieving this, but I also would not find using something like DEFMETHOD* instead of DEFMETHOD very bad and then you have all liberty you want. As I see it the MOP was created for achieving high flexibility, but not high performance, and so implementations like CMUCL or SBCL have a slightly similar but more lowlevel mechanism (compiler transforms, IIRC) how one can instruct the compiler to optimize operations with type information that is known at compile time.
Sigh. I was hoping to avoid doing all the superclass ordering and stuff, oh well. I sort of want to do things like the macro generate-typed-copy! in the file: https://github.com/enupten/matlisp/blob/tensor/src/level-1/copy.lisp without having to read things from a Hashtable everytime. Maybe writing a new object system is overkill, and I should just use a macro like with-slots.
What about doing a type-specialized compilation on-demand as I do in femlisp/src/matlisp/blas-basic.lisp?
Alternatively, this could also be triggered when NO-APPLICABLE-METHOD is called.
Akshay
Apropos: I am still trying to build and run your Matlisp without success. First, I had difficulties because f77 did not know the "exit" command used in "iladlr.f", for example. Using gfortran compiled at least the Fortran code, however after compilation I am left in a state with apparently nothing new available.
Is this the Intel compiler ?
From the Manpages on my system
gfortran - GNU Fortran compiler
f77=fort77 - invoke f2c Fortran translator transparently, like a compiler
I think this has changed recently. Some time ago, f77 was the GNU Fortran compiler.
[...] ; /home/neuss/.cache/common-lisp/sbcl-1.1.5.5-203e2ac-linux-x64/home/neuss/matlisp/src/sugar/ASDF-TMP-seq.fasl written ; compilation finished in 0:00:00.022 ; ; compilation unit finished ; printed 8 notes
** MATLISP is loaded. Type (HELP MATLISP) to see a list of available symbols. To use matlisp:
(use-package "MATLISP") or (in-package "MATLISP-USER")
- (help matlisp)
; in: HELP MATLISP ; (HELP MATLISP) ; ; caught STYLE-WARNING: ; undefined function: HELP ; ; caught WARNING: ; undefined variable: MATLISP ; ; compilation unit finished ; Undefined function: ; HELP ; Undefined variable: ; MATLISP ; caught 1 WARNING condition ; caught 1 STYLE-WARNING condition
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "main thread" RUNNING {10029D9833}>: The variable MATLISP is unbound.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name): 0: [ABORT] Exit debugger, returning to top level.
((LAMBDA ())) 0] 0
- (apropos "matlisp")
COMMON-LISP-USER::MATLISP :MATLISP (bound) :MATLISP-TESTS (bound) :MATLISP-USER (bound) *MATLISP-VERSION* (bound) MATLISP MATLISP-HERALD (fbound) MATLISP-NAME MATLISP-VERSION (fbound) SAVE-MATLISP (fbound) MATLISP-FFI::MATLISP-SPECIALIZED-ARRAY MATLISP-SYSTEM::MATLISP MATLISP-SYSTEM::MATLISP-CONDITIONS MATLISP-SYSTEM::MATLISP-CONFIG MATLISP-SYSTEM::MATLISP-PACKAGES MATLISP-SYSTEM::MATLISP-TESTS MATLISP-SYSTEM::MATLISP-UTILITIES
Yes, the old help system isn't yet incorporated. I'm sorry that you've to tread through my undocumented code.
Assuming you want to test the GEMM, you'd want to do something like:
(in-package :matlisp)
(let ((A (make-real-tensor 1000 1000)) (B (make-real-tensor 1000 1000))) ;;Slow and dynamic (time (mod-dotimes (idx (dimensions A)) do (progn (setf (tensor-ref A idx) (random 1d0) (tensor-ref B idx) (random 1d0))))) ;;Faster (although random slows it down quite a bit). #+nil (time (let-typed ((sto-a (store A) :type real-store-vector) (sto-b (store B) :type real-store-vector)) (mod-dotimes (idx (dimensions A)) with (linear-sums (of-a (strides A) (head A)) (of-b (strides B) (head B))) do (progn (real-typed.value-writer (random 1d0) sto-a of-a) (real-typed.value-writer (random 1d0) sto-b of-b))))) ;;Use lisp (let ((*real-l3-fcall-lb* 1000)) (time (gemm 1d0 A B nil nil))) ;;Use fortran (let ((*real-l3-fcall-lb* 0)) (time (gemm 1d0 A B nil nil))))
I realised I haven't actually added all my "test" files into the repository. I'll add them to the repo today.
On my computer the timings are something like: Lisp: 3.2s C (tests/mm.c): 2.2s Goto: 0.2s
Akshay
OK, this works.
Some further questions and remarks:
- Do you have also a reader macro like [...] in old Matlisp? And could you illustrate how slicing works?
- Looking at how complicated e.g. "gemm.lisp" is, I am not sure if doing this in CL is really worthwile. Optimizing for small matrices might be the wrong idea from the beginning.
- I would be interested in the minimal amount of code necessary for adding some new LAPACK routine. If possible, the stub should be even smaller than in femlisp/src/matlisp/ggev.lisp and femlisp/src/matlisp/hgev.lisp (solutions of generalized eigenvalue problems).
- I really am interested in single-float stuff too, because I will look more closely in generating high-performance code in the next future. In this domain, using single-float is often interesting, because it needs only half the memory and using it can lead to double efficiency in situations where memory bandwidth is the limiting factor.
Nicolas