[Antik-devel] Matlisp, CLOS

Nicolas Neuss neuss at math.fau.de
Fri Mar 8 12:09:00 UTC 2013


[I added some more people to the CC]

Akshay Srinivasan <akshaysrinivasan at gmail.com> writes:

> At Thu, 07 Mar 2013 10:35:46 +0100,
> Nicolas Neuss wrote:
>> 
>> Akshay Srinivasan <akshaysrinivasan at 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

-- 
Nicolas Neuss    neuss at math.fau.de





More information about the antik-devel mailing list