指数运算符性能
好吧,也许这里有一个愚蠢的问题,但我目前正在通过完成projecteuler.net上的问题来学习haskell,
我遇到了一个有趣的观察,并希望有人能够阐明为什么事情是这样的。
作为参考,我正在实施问题#29 这是我的发现,
nub $ [ a^^b | a <- [2..100], b <- [2..100] ]
我观察到,对于上面列出的输入,使用 ^^
运算符比 **
更快,而 **
又比 ^
更快。
我的问题很简单,为什么?这些运算符中的每一个都适用于不同的类型类别。我的猜测是发生了一些类型转换,但我希望 ^
的操作速度更快,但看起来实际上恰恰相反。
谢谢!
Okay maybe a silly question here, but I am currently learning haskell by completing problems on projecteuler.net
I ran into an interesting observation and was hoping someone could shed some light why things are the way they are.
For reference, I was implementing Problem #29
Here's what I came up
nub $ [ a^^b | a <- [2..100], b <- [2..100] ]
I observed that using the ^^
operator is faster than **
which is faster than ^
for the input listed above.
My question is simply, why? Each of these operators applies to different type classes. My guess is there is some type conversions taking place, but I would expect ^
to be the faster of the operations, when it seems it's actually the oposite.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
所有的时间都花在了
nub
上。使用^^
和**
,您将在[Double]
上执行nub
。对于^
,它是[Integer]
上的nub
,并且比较大整数比比较双精度数慢。All the time is spent on
nub
. With^^
and**
you're doingnub
on[Double]
. With^
it isnub
on[Integer]
, and comparing big integers is slower than comparing doubles.**
和^^
使用Double
,但^
使用Integer
。您确实无法将浮点运算与大整数函数进行比较。查看实现^
。在您的代码中,以下情况正确:
**
在硬件中实现。^
在尾递归循环中使用大Integer
。^^
是相同的,除了Double
。所以你对他们相对表现的观察是有道理的。
**
and^^
are usingDouble
, but^
is usingInteger
. You really can’t compare a floating point operation to a big integer function. Take a look at the implementation of^
.In your code, the following are true:
**
is implemented in hardware.^
uses bigInteger
in a tail-recursive loop.^^
is the same, except withDouble
.So your observations about their relative performance make sense.
我在解决 Project Euler 问题时发现,类型可以对运行时性能产生巨大影响。例如:
都有非常不同的性能。想象一下,当我发现仅仅让编译器推断 foo 的最通用类型而不是自己指定它会导致性能不佳时,我会感到多么惊讶。
性能(显然)也高度依赖于您的环境:您运行的是编译型还是解释型?优化还是未优化?关键是,在某些情况下,您可能在幕后拥有未装箱的原始 Int#,而不是装箱的堆分配值...不幸的是,我自己仍然是一个 n00b,我不这样做不知道什么时候你会得到一个与另一个:(
所以,也许这是一个愚蠢的答案,但如果你使用 GHC 并且熟悉 C 编程,请尝试使用
-keep-hc -files
标志比较使用^
与^^
与**
时生成的中间 C 代码。The thing I've found while working through Project Euler problems is that types can make a huge difference in runtime performance. For example:
all have very different performance. Imagine my surprise when I discovered that simply letting the compiler infer the most generic type for
foo
, rather than specifying it myself, was causing poor performance.Performance is also (obviously) highly dependent on your environment: are you running compiled or interpreted? Optimized or un-optimized? The point is that in some circumstances you might have unboxed, primitive
Int#
s under the covers rather than boxed, heap-allocated values... Unfortunately I'm still enough of a n00b myself that I don't know when you'll get one vs. the other :(So, maybe this is a dumb answer, but if you're using GHC and you're familiar with C programming, try using the
-keep-hc-files
flag to compare the intermediate C code generated when you use^
vs.^^
vs.**
.