[racket-dev] [plt] Push #27909: master branch updated

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Thu Dec 12 13:27:27 EST 2013

FWIW, my push speeds up the any-wrap/c implementation a bunch. Those two
should have similar speeds after you get that, I guess.

Robby


On Thu, Dec 12, 2013 at 11:03 AM, Neil Toronto <neil.toronto at gmail.com>wrote:

> I tried your branch that implements it and saw about 3.5x speedup for the
> `magnitude*' test. This is of course without Robby's recent first-order
> contract changes.
>
> (I think it's about 3.5x: I tried with magnitude* : Number -> Any first
> and got 2400ms on the easy tests. I changed it to magnitude* : Number ->
> Number and got 690ms. Apparently, for an `Any' return type, an `any-wrap/c'
> contract is generated instead of nothing. If that's much faster to check
> than `number?', though, the speedup is even better.)
>
> I'd love to see this with Robby's recent changes. Hint? Nudge? Please?
>
> I didn't see very much speedup with arrays (about 1.2x). Speed tests on
> the math library's distribution objects were very interesting, though, and
> indicate why the arrays might not be much faster. Here's my test program:
>
>
> #lang racket
>
> (require math/distributions)
>
> (define d (normal-dist 0 1))
>
> (printf "pdf d 0~n")
> (for ([_  (in-range 5)])
>   (time (for ([_  (in-range 100000)])
>           (pdf d 0))))
> (newline)
>
> (define p (distribution-pdf d))
> (printf "p 0~n")
> (for ([_  (in-range 5)])
>   (time (for ([_  (in-range 100000)])
>           (p 0))))
> (newline)
>
>
> The two tests are equivalent, as `pdf' just pulls the pdf function out of
> the distribution struct and applies it. In TR, the tests are exactly the
> same speed (extremely fast). In untyped Racket, on the main branch, the
> second test is 16x faster, and on your branch, it's 44x faster. (It's still
> 10x slower than TR on your branch, so again... I'd love to see your changes
> and Robby's together. :D)
>
> Neil ⊥
>
>
> On 12/12/2013 12:40 AM, Eric Dobson wrote:
>
>> Removing the return value checking is in the works. It actually is
>> removing all of the checks that would blame typed code, so higher
>> order functions/datastructure get improvements too. It is actually
>> functional the last time I checked, but lacking documentation which is
>> what is holding up merging with mainline.
>>
>> https://github.com/plt/racket/pull/453
>>
>> On Wed, Dec 11, 2013 at 7:57 PM, Robby Findler
>> <robby at eecs.northwestern.edu> wrote:
>>
>>> I see that TR's type->contract returns
>>>
>>>   (-> (flat-named-contract (quote Float) flonum?) (flat-named-contract
>>> (quote
>>> Float) flonum?))
>>>
>>> for the type (Float -> Float), but it could return
>>>
>>>   (-> (flat-named-contract (quote Float) flonum?) any)
>>>
>>> which wouldn't do any result value checking (this being different from
>>> any/c
>>> as the range of the arrow contract).
>>>
>>> Robby
>>>
>>>
>>> On Wed, Dec 11, 2013 at 6:18 PM, Neil Toronto <neil.toronto at gmail.com>
>>> wrote:
>>>
>>>>
>>>> On 12/11/2013 02:49 PM, Neil Toronto wrote:
>>>>
>>>>>
>>>>> On 12/11/2013 01:55 PM, Stephen Bloch wrote:
>>>>>
>>>>>>
>>>>>>> On Dec 11, 2013, at 2:36 PM, Neil Toronto wrote:
>>>>>>>
>>>>>>>  numeric primitives implemented in Typed Racket are faster than the
>>>>>>>> same primitives implemented in C.
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>> Whoa!  How did that happen?
>>>>>>
>>>>>
>>>>>
>>>>> Whoa! That's not what I meant! O_o
>>>>>
>>>>> I said "we might be getting close" to that. I haven't tried porting a
>>>>> numeric C primitive to TR yet, but I have a hunch that it'll still be
>>>>> slower. I'll try one now and report what I find.
>>>>>
>>>>> Neil ⊥
>>>>>
>>>>
>>>>
>>>> I can't figure out why `flsinh' is faster to call from untyped Racket
>>>> than
>>>> `sinh'. All my tests with a Typed Racket `magnitude' show calls from
>>>> untyped
>>>> code are significantly slower, except in the one case that it computes
>>>> Euclidean distance. That case is only twice as slow.
>>>>
>>>> I've attached the benchmark program. The `magnitude*' function is more
>>>> or
>>>> less a direct translation of `magnitude' from "number.c" into Typed
>>>> Racket.
>>>> Here's a summary of the results I get on my computer, in milliseconds,
>>>> for 5
>>>> million calls from untyped Racket, by data type.
>>>>
>>>>
>>>> Function         Flonum  Rational  Fixnum  Integer  Float-Complex
>>>> -------------------------------------------------------------------
>>>> magnitude*         385      419      378     414         686
>>>> magnitude           59       44       40      40         390
>>>>
>>>>
>>>> The only one that's close in relative terms is Float-Complex. The others
>>>> just call `abs'. The decompiled code doesn't show any inlining of
>>>> `magnitude', so this comparison should be good.
>>>>
>>>> I'll bet checking the return value contract (which is unnecessary) is
>>>> the
>>>> main slowdown. It has to check for number of values.
>>>>
>>>> For comparison, here are the timings for running the benchmarks in TR
>>>> with
>>>> #:no-optimize:
>>>>
>>>>
>>>> Function         Flonum  Rational  Fixnum  Integer  Float-Complex
>>>> -------------------------------------------------------------------
>>>> magnitude*          45       70*      37     102*       318
>>>> magnitude           61       45       39      91*       394
>>>>
>>>>                                                * = unexpectedly high
>>>>
>>>>
>>>> Here's what I understand from comparing the numbers:
>>>>
>>>>   * Except for non-fixnum integers, calling `magnitude' in TR is just as
>>>> fast as in untyped Racket. I have no idea why it would be slower on big
>>>> integers. That's just weird.
>>>>
>>>>   * Calling `abs' in Racket is faster than calling `scheme_abs' in C,
>>>> except on rationals and big integers.
>>>>
>>>>   * Operating on flonums in Typed Racket, using generic numeric
>>>> functions,
>>>> is faster than doing the same in C.
>>>>
>>>> Overall, it looks like the TR code is within the same order of magnitude
>>>> (pun not intended) as the C code. I would love to try this benchmark
>>>> with
>>>> either 1) a `magnitude*' with an `AnyValues' return type; or 2) a
>>>> contract
>>>> boundary that doesn't check TR's return types for first-order functions.
>>>>
>>>> (I managed to make a `magnitude*' with type Number -> AnyValues, but TR
>>>> couldn't make a contract for it.)
>>>>
>>>> Neil ⊥
>>>>
>>>>
>>>> _________________________
>>>>    Racket Developers list:
>>>>    http://lists.racket-lang.org/dev
>>>>
>>>>
>>> _________________________
>>>    Racket Developers list:
>>>    http://lists.racket-lang.org/dev
>>>
>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/dev/archive/attachments/20131212/b411d0cc/attachment-0001.html>

Posted on the dev mailing list.