Giter Club home page Giter Club logo

static-dispatch's People

Contributors

alex-gutev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

mr-dispatch

static-dispatch's Issues

Providing compiler notes

Are there plans to provide compiler notes - and/or respecting (optimize debug) vs (optimize speed) compilation options?

Edit: What I'd intend is that (optimize speed) should directly cause an inline-declaration, while (optimize debug) should cause a notinline declaration; I'm not objectively sure that's a good idea, but subjectively, it seems good.

ASDF Style warning

   Deprecated recursive use of (ASDF/OPERATE:OPERATE 'ASDF/LISP-ACTION:LOAD-OP
   '("static-dispatch/test")) while visiting
   (ASDF/LISP-ACTION:TEST-OP "static-dispatch/test") - please use proper
   dependencies instead```

Confusion over static-dispatch-type

I am a bit confused over the disassembly I am getting with a static-dispatch-type of inline compared to function. My intuition, as well as the documentation, says that inline should result in larger code size. However that is opposite to what I am seeing:

(defun test ()
  (declare (optimize (speed 3))
           (static-dispatch-type function ref))
  (let ((a (make-aggregate :storage (make-array 3 :element-type 'single-float :initial-contents '(1.0 2.0 3.0)))))
    (declare (type aggregate a))
    (ref a 2)))
    
 ; disassembly for TEST
; Size: 282 bytes. Origin: #x53897740                         ; TEST
; 740:       49896D28         MOV [R13+40], RBP               ; thread.pseudo-atomic-bits
; 744:       498B4560         MOV RAX, [R13+96]               ; thread.alloc-region
; 748:       4C8D5820         LEA R11, [RAX+32]
; 74C:       4D3B5D68         CMP R11, [R13+104]
; 750:       0F87EB000000     JNBE L4
; 756:       4D895D60         MOV [R13+96], R11               ; thread.alloc-region
; 75A: L0:   C600CD           MOV BYTE PTR [RAX], -51
; 75D:       C6400806         MOV BYTE PTR [RAX+8], 6
; 761:       0C0F             OR AL, 15
; 763:       49316D28         XOR [R13+40], RBP               ; thread.pseudo-atomic-bits
; 767:       7402             JEQ L1
; 769:       CC09             INT3 9                          ; pending interrupt trap
; 76B: L1:   488BF8           MOV RDI, RAX
; 76E:       F30F1005A2FDFFFF MOVSS XMM0, [RIP-606]           ; [#x53897518]
; 776:       F30F114001       MOVSS [RAX+1], XMM0
; 77B:       F30F100599FDFFFF MOVSS XMM0, [RIP-615]           ; [#x5389751C]
; 783:       F30F114005       MOVSS [RAX+5], XMM0
; 788:       F30F100590FDFFFF MOVSS XMM0, [RIP-624]           ; [#x53897520]
; 790:       F30F114009       MOVSS [RAX+9], XMM0
; 795:       4883EC10         SUB RSP, 16
; 799:       BABF3D2250       MOV EDX, #x50223DBF             ; :STORAGE
; 79E:       B904000000       MOV ECX, 4
; 7A3:       48892C24         MOV [RSP], RBP
; 7A7:       488BEC           MOV RBP, RSP
; 7AA:       E813A4B8FC       CALL #x50421BC2                 ; #<FDEFN MAKE-AGGREGATE>
; 7AF:       488BC2           MOV RAX, RDX
; 7B2:       49896D28         MOV [R13+40], RBP               ; thread.pseudo-atomic-bits
; 7B6:       4D8B5D60         MOV R11, [R13+96]               ; thread.alloc-region
; 7BA:       498D4B20         LEA RCX, [R11+32]
; 7BE:       493B4D68         CMP RCX, [R13+104]
; 7C2:       0F8786000000     JNBE L5
; 7C8:       49894D60         MOV [R13+96], RCX               ; thread.alloc-region
; 7CC: L2:   498D4B0B         LEA RCX, [R11+11]
; 7D0:       41BC39020000     MOV R12D, 569
; 7D6:       4D0B65E0         OR R12, [R13-32]
; 7DA:       4C8961F5         MOV [RCX-11], R12
; 7DE:       49316D28         XOR [R13+40], RBP               ; thread.pseudo-atomic-bits
; 7E2:       7402             JEQ L3
; 7E4:       CC09             INT3 9                          ; pending interrupt trap
; 7E6: L3:   4C8D2553FDFFFF   LEA R12, [RIP-685]              ; = #x53897540
; 7ED:       4C8961FD         MOV [RCX-3], R12
; 7F1:       48894105         MOV [RCX+5], RAX
; 7F5:       488BD1           MOV RDX, RCX
; 7F8:       BF17011050       MOV EDI, #x50100117             ; NIL
; 7FD:       488BF0           MOV RSI, RAX
; 800:       48C745F004000000 MOV QWORD PTR [RBP-16], 4
; 808:       B908000000       MOV ECX, 8
; 80D:       FF7508           PUSH QWORD PTR [RBP+8]
; 810:       E9CDA3B8FC       JMP #x50421BE2                  ; #<FDEFN STATIC-DISPATCH.METHOD-FUNCTIONS::REF1>
; 815:       4D29DC           SUB R12, R11
; 818:       4154             PUSH R12
; 81A:       E8668D16FF       CALL #x52A00585                 ; CONS->R11
; 81F:       E99FFDFFFF       JMP #x538975C3
; 824:       CC14             INT3 20                         ; UNDEFINED-FUN-ERROR
; 826:       04               BYTE #X04                       ; RCX(d)
; 827:       6A11             PUSH 17
; 829:       E8578D16FF       CALL #x52A00585                 ; CONS->R11
; 82E:       E99BFEFFFF       JMP #x538976CE
; 833:       6A11             PUSH 17
; 835:       E84B8D16FF       CALL #x52A00585                 ; CONS->R11
; 83A:       E9C0FEFFFF       JMP #x538976FF
; 83F:       CC10             INT3 16                         ; Invalid argument count trap
; 841: L4:   6A21             PUSH 33
; 843:       E8CD8A16FF       CALL #x52A00315                 ; CONS->RNN
; 848:       58               POP RAX
; 849:       E90CFFFFFF       JMP L0
; 84E: L5:   6A21             PUSH 33
; 850:       E8308D16FF       CALL #x52A00585                 ; CONS->R11
; 855:       E972FFFFFF       JMP L2

compared to inline:

(defun test ()
  (declare (optimize (speed 3))
           (static-dispatch-type inline))
  (let ((a (make-aggregate :storage (make-array 3 :element-type 'single-float :initial-contents '(1.0 2.0 3.0)))))
    (declare (type aggregate a))
    (ref a 2)))
    
; disassembly for TEST
; Size: 162 bytes. Origin: #x53895C7F                         ; TEST
; C7F:       49896D28         MOV [R13+40], RBP               ; thread.pseudo-atomic-bits
; C83:       498B4560         MOV RAX, [R13+96]               ; thread.alloc-region
; C87:       4C8D5820         LEA R11, [RAX+32]
; C8B:       4D3B5D68         CMP R11, [R13+104]
; C8F:       777C             JNBE L2
; C91:       4D895D60         MOV [R13+96], R11               ; thread.alloc-region
; C95: L0:   C600CD           MOV BYTE PTR [RAX], -51
; C98:       C6400806         MOV BYTE PTR [RAX+8], 6
; C9C:       0C0F             OR AL, 15
; C9E:       49316D28         XOR [R13+40], RBP               ; thread.pseudo-atomic-bits
; CA2:       7402             JEQ L1
; CA4:       CC09             INT3 9                          ; pending interrupt trap
; CA6: L1:   488BF8           MOV RDI, RAX
; CA9:       F30F100597FFFFFF MOVSS XMM0, [RIP-105]           ; [#x53895C48]
; CB1:       F30F114001       MOVSS [RAX+1], XMM0
; CB6:       F30F10058EFFFFFF MOVSS XMM0, [RIP-114]           ; [#x53895C4C]
; CBE:       F30F114005       MOVSS [RAX+5], XMM0
; CC3:       F30F100585FFFFFF MOVSS XMM0, [RIP-123]           ; [#x53895C50]
; CCB:       F30F114009       MOVSS [RAX+9], XMM0
; CD0:       4883EC10         SUB RSP, 16
; CD4:       BABF3D2250       MOV EDX, #x50223DBF             ; :STORAGE
; CD9:       B904000000       MOV ECX, 4
; CDE:       48892C24         MOV [RSP], RBP
; CE2:       488BEC           MOV RBP, RSP
; CE5:       E8D8BEB8FC       CALL #x50421BC2                 ; #<FDEFN MAKE-AGGREGATE>
; CEA:       488B4205         MOV RAX, [RDX+5]
; CEE:       488378F904       CMP QWORD PTR [RAX-7], 4
; CF3:       7625             JBE L3
; CF5:       F30F104009       MOVSS XMM0, [RAX+9]
; CFA:       660F7EC2         MOVD EDX, XMM0
; CFE:       48C1E220         SHL RDX, 32
; D02:       80CA19           OR DL, 25
; D05:       488BE5           MOV RSP, RBP
; D08:       F8               CLC
; D09:       5D               POP RBP
; D0A:       C3               RET
; D0B:       CC10             INT3 16                         ; Invalid argument count trap
; D0D: L2:   6A21             PUSH 33
; D0F:       E801A616FF       CALL #x52A00315                 ; CONS->RNN
; D14:       58               POP RAX
; D15:       E97BFFFFFF       JMP L0
; D1A: L3:   CC24             INT3 36                         ; INVALID-VECTOR-INDEX-ERROR
; D1C:       00               BYTE #X00                       ; RAX(d)
; D1D:       8A808010         BYTE #X8A, #X80, #X80, #X10     ; 2

Is this expected behavior?

Basic usage fails to compile on SBCL 2.1.7

Trying this library out for the first time, and cannot get this basic usage to compile on SBCL 2.1.7:

(in-package #:cl-user)

(defpackage #:origin2
  (:use #:static-dispatch-cl))

(in-package #:origin2)

(defstruct (aggregate
            (:predicate nil)
            (:copier nil))
  (storage (make-array 0 :element-type 'single-float :initial-element 0.0) :type (simple-array single-float (*))))

(defgeneric ref (sequence index))

(defmethod ref ((sequence aggregate) index)
  (elt (aggregate-storage sequence) index))

(defgeneric (setf ref) (value sequence index))

(defmethod (setf ref) (value (sequence aggregate) index)
  (setf (elt (aggregate-storage sequence) index) value))

(defun test ()
  (declare (optimize (speed 3) (safety 2)))
  (let ((a (make-aggregate :storage (make-array 3 :element-type 'single-float :initial-contents '(1.0 2.0 3.0)))))
    (declare (type aggregate a))
    (ref a 2)))
    
; file: /tmp/slimegXmN46
; in: DEFUN TEST
;     (ORIGIN2::REF ORIGIN2::A 2)
; 
; caught ERROR:
;   don't know how to dump #<STANDARD-METHOD ORIGIN2::REF (AGGREGATE T) {1001A3DC23}> (default MAKE-LOAD-FORM method called).
; 
; compilation unit finished
;   caught 1 ERROR condition

Edit: Reproducible with latest Quicklisp dist version of static-dispatch as well as tip of master

static-dispatch-warn with ALL fails to parse

Using the same boilerplate in #5 and changing test to:

(defun test ()
  (declare (optimize (speed 3) (safety 2))
           (static-dispatch-warn all))
  (let ((a (make-aggregate :storage (make-array 3 :element-type 'single-float :initial-contents '(1.0 2.0 3.0)))))
    (declare (type aggregate a))
    (ref a 2)))

(added the static-dispatch-warn declaration).

Fails to parse:

; file: /tmp/slimenOeOuC
; in: DEFUN TEST
;     (ORIGIN2::REF ORIGIN2::A 2)
; 
; caught STYLE-WARNING:
;   Static dispatch for REF failed:
;     Error while parsing arguments to DESTRUCTURING-BIND:
;       invalid number of elements in
;         (:DECLARE STATIC-DISPATCH-WARN . STATIC-DISPATCH::ALL)
;       to satisfy lambda list
;         (ENTRY-KEYWORD ENTRY-VAR ENTRY-BINDING &REST ENTRY-CONS):
;       at least 3 expected, but got an improper list
; 
; compilation unit finished
;   caught 1 STYLE-WARNING condition

Compile-time (ASDF:COMPILE-OP) error

I'm not able to compile static-dispatch e.g. like this:

CL-USER> (asdf:oos 'asdf:compile-op :static-dispatch :force t)

due to this error:

; compiling file "/nix/store/ndsgsqm6gg0jcw4v4fbrlvkk8a9ax4r1-nixlisp-bundle-1.0.0/lib/common-lisp/bundle/software/static-dispatch-20210807-git/src/combinations.lisp" (written 01 JAN 1970 01:00:01 AM):
; processing (IN-PACKAGE #:STATIC-DISPATCH)
; processing (DEFINE-METHOD-COMBINATION% STANDARD ...)
[...]
The function
(COMMON-LISP:SETF STATIC-DISPATCH::COMBINATION-FUNCTION) is
undefined.
   [Condition of type UNDEFINED-FUNCTION]

The problem seems to be that define-method-combination% expands into code that is (eval-when (:compile-toplevel :load-toplevel :execute) ...) and includes a call to (setf combination-function) but that this is not defined at compile-time.

I'm not sure what the root issue is but it seems to be either too much or too little being declared to run at compile-time.

Hints would be appreciated as this is an obstacle to including static-dispatch in my packaging framework of choice (Nix.)

method-descriptions are not honored

method-descriptions are not honored for static-dispatch:defgeneric forms, and dispatch falls back to dynamic mode.

It would be nice to support methods installed in this way, or extend the warning capability to inform the user of such a fallback.

find-method% conditionalization for LispWorks

find-method% in "src/common.lisp" is currently conditionalize such on clisp it constructs the specializers as it should, but on other implementation it doesn't.

On LispWorks, it should do the same as it does on clisp.

I actually found the issue when running tests for another system, "picl/tests", and just removing the conditinalization fixed it. It should work on all implementations, because that is what the standard says.

Help needed: 3 different performance timings with same code

I am experiencing 3 different performance results consistently with the same code, depending on how I load it. Here is the test code:

(in-package #:cl-user)

(defpackage #:origin2
  (:use #:static-dispatch-cl))

(in-package #:origin2)

(defstruct (aggregate
            (:predicate nil)
            (:copier nil))
  (storage (make-array 0 :element-type 'single-float :initial-element 0.0) :type (simple-array single-float (*))))

(defgeneric ref (sequence index)
  (:method ((sequence aggregate) index)
    (elt (aggregate-storage sequence) index)))

(defun test ()
  (declare (optimize (speed 3)))
  (let ((a (make-aggregate :storage (make-array 3 :element-type 'single-float :initial-contents '(1.0 2.0 3.0)))))
    (declare (type aggregate a))
    (dotimes (i (expt 10 9))
      (ref a 2))))

Clearing FASL's, loading this code into my image on SBCL 2.1.7, and issuing:

(progn
  (sb-ext:gc :full t)
  (time (test)))

I get these results consistently:

Evaluation took:
  7.146 seconds of real time
  7.130177 seconds of total run time (7.130177 user, 0.000000 system)
  99.78% CPU
  20 lambdas converted
  14,232,702,075 processor cycles
  1,080,336 bytes consed

If I now re-compile the #'test function in the same image, and re-run the test I consistently get:

Evaluation took:
  0.350 seconds of real time
  0.351234 seconds of total run time (0.351196 user, 0.000038 system)
  100.29% CPU
  701,597,093 processor cycles
  0 bytes consed

If I wrap the defgeneric in (eval-when (:compile-toplevel :load-toplevel :execute) ...), clear FASL's, loading the code, and re-run the test, I consistently get:

Evaluation took:
  0.583 seconds of real time
  0.579642 seconds of total run time (0.579642 user, 0.000000 system)
  99.49% CPU
  1,157,429,524 processor cycles
  0 bytes consed

I get no warnings from static-dispatch in all 3 cases, and everything compiles cleanly. I would like to know why these differences are occurring, and how I would get the results of the second test above from a clean image (instead of manually recompiling the function after loading). Thank you for your help.

Error during compiler-macroexpansion of

I wrote a small demo:

(ql:quickload 'static-dispatch)

(declaim (inline sum))
(defgeneric sum (a b)
  (:documentation "sum two values"))

(static-dispatch:defmethod sum ((a fixnum) (b fixnum))
  (declare (optimize (speed 3) (safety 0) (debug 0)))
  (+ a b))

(defun test-sum-inline (a b)
  (declare (optimize (speed 3) (safety 0) (debug 0))
           (type fixnum a b))
  (sum a b))

but SBCL v1.3.21 with errors occur when compile function test-sum-inline:

; in: DEFUN TEST-SUM-INLINE
;     (SUM A B)
; 
; caught WARNING:
;   Error during compiler-macroexpansion of (SUM A B). Use *BREAK-ON-SIGNALS* to
;   intercept.
;   
;    invalid number of arguments: 1
; 
; compilation unit finished
;   caught 1 WARNING condition

Did I use static-dispatch in the wrong way? Could you please give me a working demo?

Some systems failed to build for Quicklisp dist

Building with SBCL 2.1.10 / ASDF 3.3.5 for quicklisp dist creation.

Trying to build commit id 8dd50fa

static-dispatch/test fails to build with the following error:

; caught WARNING:
;   * is not permitted as an argument to the FUNCTION type specifier
; 
; caught WARNING:
;   * is not permitted as an argument to the FUNCTION type specifier
...
Unhandled UIOP/LISP-BUILD:COMPILE-FILE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING {1001C08103}>: COMPILE-FILE-ERROR while compiling #<CL-SOURCE-FILE "static-dispatch/test" "test" "internals">

Full log here

ignore/ignorable declarations in methods emit style-warnings

Consider the following generic function intended to access an element from a matrix of column vectors. For the 2x1 matrix type, aka mathematical vector, the column parameter is declared ignored.

(defgeneric ref (aggregate row &optional column))

(defmethod ref ((aggregate vec2) row &optional column)
  (declare (ignore column))
  (locally (declare (optimize (safety 0)))
    (aref (storage aggregate) index)))

;; in a later compilation unit
(declaim (ftype (function (vec2 (integer 0 2)) single-float) test))
(defun test (vec2 index)
  (declare (optimize speed))
  (ref vec2 index))

However:

; in: DEFUN TEST
;     (ORIGIN2::REF ORIGIN2::VEC2 ORIGIN2::INDEX)
; 
; caught STYLE-WARNING:
;   IGNORE declaration for a variable from outer scope: COLUMN

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.