提高 Haskell 性能的简单技巧(针对 ProjectEuler 问题)?

19 浏览
0 Comments

提高 Haskell 性能的简单技巧(针对 ProjectEuler 问题)?

我刚开始学习编程,正在通过阅读和解决Project Euler的问题来学习Haskell。当然,最重要的是要改善这些问题的性能,通过使用更好的算法。然而,对我来说,显然还有其他简单易懂的方法可以提高性能。一个随意的搜索带来了这个问题和这个问题,它们提供了以下提示:

  • 使用ghc标志-O2和-fllvm。</ li>
  • 使用类型Int,而不是Integer,因为它是未装箱的(甚至使用Int64而不是Integer)。这需要输入函数,而不是让编译器即兴创作。
  • 使用rem而不是mod进行除法测试。</ li>
  • 使用Schwartzian变换在适当的时候。</ Li>
  • 在递归函数中使用累加器(我相信这是一个尾部递归优化)。</ Li>
  • 备忘录(?)</ Li>

(一个答案还提到了worker / wrapper变换,但这似乎相当先进。)

问题:</ strong>在Haskell中有哪些其他简单的优化可以在Project Euler样式的问题上提高性能?还有其他特定于Haskell(或函数式编程?)的想法或特性可以用于加速解决Project Euler问题的解决方案吗?反之,人们应该注意什么?有哪些常见但低效的事情需要避免?</ p>

admin 更改状态以发布 2023年5月24日
0
0 Comments

一个简单的建议是使用 `hlint`,它是一个检查您的源代码并就语法方面提出改进建议的程序。这可能不会增加速度,因为很可能已经由编译器或惰性评估完成。但在某些情况下它可能会帮助编译器。此外,它将使您成为更好的 Haskell 程序员,因为您将学习更好的做事方式,并且可能更容易理解和分析您的程序。\n\n其中一些示例可以从 http://community.haskell.org/~ndm/darcs/hlint/hlint.htm 上找到,例如:\n\n

darcs-2.1.2\src\CommandLine.lhs:94:1: Error: Use concatMap
Found:
  concat $ map escapeC s
Why not:
  concatMap escapeC s

\n\n和\n\n

darcs-2.1.2\src\Darcs\Patch\Test.lhs:306:1: Error: Use a more efficient monadic variant
Found:
  mapM (delete_line (fn2fp f) line) old
Why not:
  mapM_ (delete_line (fn2fp f) line) old

\n\n我认为在解决 Project Euler 问题时,您可以做出的最大改进是了解问题并消除不必要的计算。即使您不理解所有内容,您也可以进行一些小的修复,这将使您的程序运行速度加倍。假设您正在寻找小于 1,000,000 的素数,则当然可以执行 `filter isPrime [1..1000000]`。但是如果您思考一下,就可以意识到好吧,大于 2 的偶数都不是素数,因此您已经删除了(大约)一半的工作。代替使用 `filter isPrime [1..1000000]`,您可以使用 `[1,2] ++ filter isPrime [3,5..999999]`。

0
0 Comments

这里有一些我经常参考的Johan Tibell的好幻灯片:

Haskell性能模式

0