guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Take some lowhanging fruit to speed up R6RS fixnum operation


From: Andreas Rottmann
Subject: Re: [PATCH] Take some lowhanging fruit to speed up R6RS fixnum operations
Date: Fri, 25 Mar 2011 13:16:21 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux)

Andreas Rottmann <address@hidden> writes:

> address@hidden (Ludovic Courtès) writes:
>
>> Hi Andreas,
>>
>> I’m all for your suggestion.
>>
>> Andreas Rottmann <address@hidden> writes:
>>
>>> +  (define-syntax define-fxop*
>>> +    (syntax-rules ()
>>> +      ((_ name op)
>>> +       (define name
>>> +    (case-lambda
>>> +      ((x y)
>>> +       (assert-fixnum x y)
>>> +       (op x y))
>>> +      (args
>>> +       (assert-fixnums args)
>>> +       (apply op args)))))))
>>> +
>>> +  (define-fxop* fx=? =)
>>
>> How about making something like this (untested):
>>
>>   (define-syntax define-fxop*
>>     (syntax-rules ()
>>       ((_ name op)
>>        (define-syntax name
>>          (lambda (s)
>>            (syntax-case s ()
>>              ((_ x y)
>>               #'(begin
>>                   (assert-fixnum x y)
>>                   (op x y)))
>>              ((_ args ...)
>>               #'(apply op args))
>>              (_ #'op)))))))
>>
>> This way, there’d be no procedure call involved and ‘=’, ‘+’, etc. would
>> use the corresponding instruction in the base case.
>>
> That's an excellent idea, and would probably boost performance quite a
> bit.
>
Sorry to reply to myself, but new evidence has been produced :-).

Using the following macro:

  (define-syntax define-fxop*
    (lambda (stx)
      (define prefix (string->symbol "% "))
      (define (make-procedure-name name)
        (datum->syntax name
                       (symbol-append prefix (syntax->datum name)
                                      '-procedure)))
      (syntax-case stx ()
        ((_ name op)
         (with-syntax ((proc-name (make-procedure-name #'name)))
           #'(begin
               (define (proc-name . args)
                 (assert-fixnums args)
                 (apply op args))
               (define-syntax name
                 (lambda (stx)
                   (syntax-case stx ()
                     ((_ x-expr y-expr)
                      #'(let ((x x-expr)
                              (y y-expr))
                          (assert-fixnum x y)
                          (op x y)))
                     ((_ . args)
                      #'(proc-name . args))
                     (_
                      (identifier? stx)
                      #'proc-name))))))))))

It turns out that this does not have a great effect on the efficiency;
here are the numbers:

    * stable-2.0 + rotty/wip-fixnum-speed (simple define-fxop*, clever fixnum?)

    #+begin_example
    % _build/meta/guile -e main -s benchmark-suite/guile-benchmark 
--benchmark-suite benchmarks r6rs-arithmetic.bm
    ;; running guile version 2.0.0.133-e47c9-dirty
    ;; calibrating the benchmarking framework...
    ;; framework time per iteration: 1.1444091796875e-7
    ("r6rs-arithmetic.bm: fixnum: fixnum? [yes]" 10000000 user 3.42 benchmark 
2.2755908203125 bench/interp 2.2755908203125 gc 0.0)
    ("r6rs-arithmetic.bm: fixnum: fixnum? [no]" 10000000 user 3.42 benchmark 
2.2755908203125 bench/interp 2.2755908203125 gc 0.0)
    ("r6rs-arithmetic.bm: fixnum: fxxor [2]" 10000000 user 6.96 benchmark 
5.8155908203125 bench/interp 5.8155908203125 gc 0.0)

    scheme@(guile-user)> ,time (run-benchmark)
    clock utime stime cutime cstime gctime
    23.81 23.76  0.00   0.00   0.00   0.00
    #+end_example

    * stable-2.0 + rotty/wip-fixnum-speed (macro-based define-fxop*, clever 
fixnum?)

    #+begin_example
    % _build/meta/guile -e main -s benchmark-suite/guile-benchmark 
--benchmark-suite benchmarks r6rs-arithmetic.bm
    ;; running guile version 2.0.0.133-e47c9-dirty
    ;; calibrating the benchmarking framework...
    ;; framework time per iteration: 1.52587890625e-7
    ("r6rs-arithmetic.bm: fixnum: fixnum? [yes]" 10000000 user 3.4 benchmark 
1.87412109375 bench/interp 1.87412109375 gc 0.0)
    ("r6rs-arithmetic.bm: fixnum: fixnum? [no]" 10000000 user 3.42 benchmark 
1.89412109375 bench/interp 1.89412109375 gc 0.0)
    ("r6rs-arithmetic.bm: fixnum: fxxor [2]" 10000000 user 6.72 benchmark 
5.19412109375 bench/interp 5.19412109375 gc 0.0)

    scheme@(guile-user)> ,time (run-benchmark)
    clock utime stime cutime cstime gctime
    22.76 22.73  0.00   0.00   0.00   0.00
    #+end_example

So, that's around 5% improvment (on the ZIP benchmark) for an IMHO
significantly more hackish implementation.  I'm not sure that's worth
it. WDYT?

Regards, Rotty
-- 
Andreas Rottmann -- <http://rotty.yi.org/>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]