benchmarking a function that returns an unlifted type

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

benchmarking a function that returns an unlifted type

Richard Eisenberg-4
Apologies for a newbie question, but I am seeking advice on how to benchmark a pure function that returns an unlifted type. I've heard tell that `criterion` is good for benchmarking, and so I'm using that library (but have no particular allegiance to it, if something else is better).

Specifically, I'm comparing a function over unlifted types with the same function written over lifted types, trying to observe how much we pay for the boxing/unboxing. To benchmark the lifted version, I just use criterion's whnf function. That seems to be working splendidly. Of course, whnf doesn't work over unlifted types, so I found its source code and inlined it. This compiles. But it doesn't work! No matter what I do, the unlifted version measures in the nanoseconds. I'm guessing that GHC "cleverly" is avoiding recomputation. How can I stop this?

Here is my code:

> main :: IO ()
> main = do
>   initializeTime
>   let lifted   = whnf fastSumPrimes 100000
>
>       unlifted = Benchmarkable go
>         where
>           go n
>             | n <= 0    = return ()
>             | otherwise = let x = fastSumPrimes# 100000# in go (n-1)
>
>   benchmark lifted
>   benchmark unlifted

I've tried increasing the argument in the unlifted case, to no avail. I've also tried using `case` instead of `let`. -ddump-simpl suggests that fastSumPrimes# is really being called, but I'm dubious.

Can anyone offer advice?

Thanks!
Richard
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: benchmarking a function that returns an unlifted type

Oleg Grenrus
Won't boxing at the end work, that should have only single
unboxing/boxing action:

    unlifted = whnf (\Int# n -> Int# (fastSumPrimes# n)) 100000

- Oleg

On 18.03.2017 19:32, Richard Eisenberg wrote:

> Apologies for a newbie question, but I am seeking advice on how to benchmark a pure function that returns an unlifted type. I've heard tell that `criterion` is good for benchmarking, and so I'm using that library (but have no particular allegiance to it, if something else is better).
>
> Specifically, I'm comparing a function over unlifted types with the same function written over lifted types, trying to observe how much we pay for the boxing/unboxing. To benchmark the lifted version, I just use criterion's whnf function. That seems to be working splendidly. Of course, whnf doesn't work over unlifted types, so I found its source code and inlined it. This compiles. But it doesn't work! No matter what I do, the unlifted version measures in the nanoseconds. I'm guessing that GHC "cleverly" is avoiding recomputation. How can I stop this?
>
> Here is my code:
>
>> main :: IO ()
>> main = do
>>   initializeTime
>>   let lifted   = whnf fastSumPrimes 100000
>>
>>       unlifted = Benchmarkable go
>>         where
>>           go n
>>             | n <= 0    = return ()
>>             | otherwise = let x = fastSumPrimes# 100000# in go (n-1)
>>
>>   benchmark lifted
>>   benchmark unlifted
> I've tried increasing the argument in the unlifted case, to no avail. I've also tried using `case` instead of `let`. -ddump-simpl suggests that fastSumPrimes# is really being called, but I'm dubious.
>
> Can anyone offer advice?
>
> Thanks!
> Richard
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: benchmarking a function that returns an unlifted type

David Feuer
In reply to this post by Richard Eisenberg-4
The critical feature of whnf (as I understand it) is that GHC does not use the static argument transformation. The function passed to "go" therefore doesn't inline into it. So you'll have to write your version in some fashion that similarly prevents undesirable inlining. Could you just copy the code and specialize it to the desired type?

On Mar 18, 2017 1:32 PM, "Richard Eisenberg" <[hidden email]> wrote:
Apologies for a newbie question, but I am seeking advice on how to benchmark a pure function that returns an unlifted type. I've heard tell that `criterion` is good for benchmarking, and so I'm using that library (but have no particular allegiance to it, if something else is better).

Specifically, I'm comparing a function over unlifted types with the same function written over lifted types, trying to observe how much we pay for the boxing/unboxing. To benchmark the lifted version, I just use criterion's whnf function. That seems to be working splendidly. Of course, whnf doesn't work over unlifted types, so I found its source code and inlined it. This compiles. But it doesn't work! No matter what I do, the unlifted version measures in the nanoseconds. I'm guessing that GHC "cleverly" is avoiding recomputation. How can I stop this?

Here is my code:

> main :: IO ()
> main = do
>   initializeTime
>   let lifted   = whnf fastSumPrimes 100000
>
>       unlifted = Benchmarkable go
>         where
>           go n
>             | n <= 0    = return ()
>             | otherwise = let x = fastSumPrimes# 100000# in go (n-1)
>
>   benchmark lifted
>   benchmark unlifted

I've tried increasing the argument in the unlifted case, to no avail. I've also tried using `case` instead of `let`. -ddump-simpl suggests that fastSumPrimes# is really being called, but I'm dubious.

Can anyone offer advice?

Thanks!
Richard
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Loading...