指数运算符性能

发布于 2024-12-12 02:20:09 字数 494 浏览 0 评论 0原文

好吧,也许这里有一个愚蠢的问题,但我目前正在通过完成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技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

⒈起吃苦の倖褔 2024-12-19 02:20:09

所有的时间都花在了nub上。使用 ^^**,您将在 [Double] 上执行 nub。对于^,它是[Integer]上的nub,并且比较大整数比比较双精度数慢。

All the time is spent on nub. With ^^ and ** you're doing nub on [Double]. With ^ it is nub on [Integer], and comparing big integers is slower than comparing doubles.

↘人皮目录ツ 2024-12-19 02:20:09

**^^ 使用 Double,但 ^ 使用 Integer。您确实无法将浮点运算与大整数函数进行比较。查看实现^

在您的代码中,以下情况正确:

  • ** 在硬件中实现。
  • ^ 在尾递归循环中使用大Integer
  • ^^ 是相同的,除了 Double

所以你对他们相对表现的观察是有道理的。

** and ^^ are using Double, but ^ is using Integer. 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 big Integer in a tail-recursive loop.
  • ^^ is the same, except with Double.

So your observations about their relative performance make sense.

苍风燃霜 2024-12-19 02:20:09

我在解决 Project Euler 问题时发现,类型可以对运行时性能产生巨大影响。例如:

foo :: Integral a => a -> a
foo' :: Integer -> Integer
foo'' :: Int -> Int

都有非常不同的性能。想象一下,当我发现仅仅让编译器推断 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:

foo :: Integral a => a -> a
foo' :: Integer -> Integer
foo'' :: Int -> Int

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. **.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文