- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我感觉答案是肯定的,而且这不仅限于 Haskell。例如,尾部调用优化将内存需求从 O(n) 更改为 O(l),对吗?
我真正关心的是:在 Haskell 上下文中,在推理程序的性能和大小时,期望了解编译器优化的哪些内容?
在Scheme中,你可以认为一些优化是理所当然的,比如TCO,只要你使用的是符合规范的解释器/编译器。
最佳答案
是的,特别是 GHC 执行严格性分析,这可以将具有意外惰性的程序的空间使用量从 O(n) 大幅减少到 O(1 )。
例如,考虑这个简单的程序:
$ cat LazySum.hs
main = print $ sum [1..100000]
由于 sum
并不假定加法运算符是严格的,(它可能与 Num
实例一起使用,其中 (+)
是懒惰的),会导致分配大量的thunk。如果未启用优化,则不会执行严格性分析。
$ ghc --make LazySum.hs -rtsopts -fforce-recomp
[1 of 1] Compiling Main ( LazySum.hs, LazySum.o )
Linking LazySum ...
$ ./LazySum +RTS -s
./LazySum +RTS -s
5000050000
22,047,576 bytes allocated in the heap
18,365,440 bytes copied during GC
6,348,584 bytes maximum residency (4 sample(s))
3,133,528 bytes maximum slop
15 MB total memory in use (0 MB lost due to fragmentation)
Generation 0: 23 collections, 0 parallel, 0.04s, 0.03s elapsed
Generation 1: 4 collections, 0 parallel, 0.01s, 0.02s elapsed
INIT time 0.00s ( 0.00s elapsed)
MUT time 0.01s ( 0.03s elapsed)
GC time 0.05s ( 0.04s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 0.06s ( 0.07s elapsed)
%GC time 83.3% (58.0% elapsed)
Alloc rate 2,204,757,600 bytes per MUT second
Productivity 16.7% of total user, 13.7% of total elapsed
但是,如果我们在启用优化的情况下进行编译,严格性分析器将确定,由于我们对 Integer
使用已知严格的加法运算符,因此编译器知道它是安全的提前评估 thunk,因此程序在恒定空间中运行。
$ ghc --make -O2 LazySum.hs -rtsopts -fforce-recomp
[1 of 1] Compiling Main ( LazySum.hs, LazySum.o )
Linking LazySum ...
$ ./LazySum +RTS -s
./LazySum +RTS -s
5000050000
9,702,512 bytes allocated in the heap
8,112 bytes copied during GC
27,792 bytes maximum residency (1 sample(s))
20,320 bytes maximum slop
1 MB total memory in use (0 MB lost due to fragmentation)
Generation 0: 18 collections, 0 parallel, 0.00s, 0.00s elapsed
Generation 1: 1 collections, 0 parallel, 0.00s, 0.00s elapsed
INIT time 0.00s ( 0.00s elapsed)
MUT time 0.01s ( 0.02s elapsed)
GC time 0.00s ( 0.00s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 0.01s ( 0.02s elapsed)
%GC time 0.0% (2.9% elapsed)
Alloc rate 970,251,200 bytes per MUT second
Productivity 100.0% of total user, 55.0% of total elapsed
请注意,如果我们自己添加严格性,即使没有优化,我们也可以获得恒定的空间:
$ cat StrictSum.hs
import Data.List (foldl')
main = print $ foldl' (+) 0 [1..100000]
$ ghc --make StrictSum.hs -rtsopts -fforce-recomp
[1 of 1] Compiling Main ( StrictSum.hs, StrictSum.o )
Linking StrictSum ...
$ ./StrictSum +RTS -s
./StrictSum +RTS -s
5000050000
9,702,664 bytes allocated in the heap
8,144 bytes copied during GC
27,808 bytes maximum residency (1 sample(s))
20,304 bytes maximum slop
1 MB total memory in use (0 MB lost due to fragmentation)
Generation 0: 18 collections, 0 parallel, 0.00s, 0.00s elapsed
Generation 1: 1 collections, 0 parallel, 0.00s, 0.00s elapsed
INIT time 0.00s ( 0.00s elapsed)
MUT time 0.00s ( 0.01s elapsed)
GC time 0.00s ( 0.00s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 0.00s ( 0.01s elapsed)
%GC time 0.0% (2.1% elapsed)
Alloc rate 9,702,664,000,000 bytes per MUT second
Productivity 100.0% of total user, 0.0% of total elapsed
严格性往往是比尾部调用更大的问题,aren't really a useful concept in Haskell ,因为Haskell的评估模型。
关于haskell - 编译器优化(例如 ghc -O2)可以更改程序的顺序(时间或存储)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7635805/
在使用 requests 库中的状态代码时,我遇到了一些奇怪的事情。每个 HTTP 状态代码都有一个常量,有些具有别名(例如,包括 200 的复选标记): url = 'https://httpbin
这是我得到的代码,但我不知道这两行是什么意思: o[arr[i]] = o[arr[i]] || {}; o = o[arr[i]]; 完整代码: var GLOBAL={}; GLOBAL.name
所以这个问题的答案What is the difference between Θ(n) and O(n)? 指出“基本上,当我们说算法是 O(n) 时,它也是 O(n2)、O(n1000000)、O
这是一个快速的想法;有人会说 O(∞) 实际上是 O(1) 吗? 我的意思是它不依赖于输入大小? 所以在某种程度上它是恒定的,尽管它是无限的。 或者是唯一“正确”的表达方式 O(∞)? 最佳答案 无穷
这是真的: log(A) + log(B) = log(A * B) [0] 这也是真的吗? O(log(A)) + O(log(B)) = O(log(A * B)) [1] 据我了解 O(f
我正在解决面试练习的问题,但我似乎无法找出以下问题的时间和空间复杂度的答案: Given two sorted Linked Lists, merge them into a third list i
我了解 Big-Oh 表示法。但是我该如何解释 O(O(f(n))) 是什么意思呢?是指增长率的增长率吗? 最佳答案 x = O(n)基本上意味着 x <= kn对于一些常量 k . 因此 x = O
我正在编写一个函数,该函数需要一个对象和一个投影来了解它必须在哪个字段上工作。 我想知道是否应该使用这样的字符串: const o = { a: 'Hello There' }; funct
直觉上,我认为这三个表达式是等价的。 例如,如果一个算法在 O(nlogn) + O(n) 或 O(nlogn + n) 中运行(我很困惑),我可以假设这是一个O(nlogn) 算法? 什么是真相?
根据 O'Reilly 的 Python in a Nutshell 中的 Alex Martelli,复杂度类 O(n) + O(n) = O(n)。所以我相信。但是我很困惑。他解释说:“N 的两个
O(n^2)有什么区别和 O(n.log(n)) ? 最佳答案 n^2 的复杂性增长得更快。 关于big-o - 大 O 符号 : differences between O(n^2) and O(n
每当我收到来自 MS outlook 的电子邮件时,我都会收到此标记 & nbsp ; (没有空格)哪个显示为?在 <>. 当我将其更改为 ISO-8859-1 时,浏览器页面字符集编码为 UTF-8
我很难理解 Algorithms by S. Dasgupta, C.H. Papadimitriou, and U.V. Vazirani - page 24 中的以下陈述它们将 O(n) 的总和表
我在面试蛋糕上练习了一些问题,并在问题 2给出的解决方案使用两个单独的 for 循环(非嵌套),解决方案提供者声称他/她在 O(n) 时间内解决了它。据我了解,这将是 O(2n) 时间。是我想错了吗,
关于 Java 语法的幼稚问题。什么 T accept(ObjectVisitorEx visitor); 是什么意思? C# 的等价物是什么? 最佳答案 在 C# 中它可能是: O Accept(
假设我有一个长度为 n 的数组,我使用时间为 nlogn 的排序算法对它进行了排序。得到这个排序后的数组后,我遍历它以找到任何具有线性时间的重复元素。我的理解是,由于操作是分开发生的,所以时间是 O(
总和 O(1)+O(2)+ .... +O(n) 的计算结果是什么? 我在某处看到它的解决方案: O(n(n+1) / 2) = O(n^2) 但我对此并不满意,因为 O(1) = O(2) = co
这个问题在这里已经有了答案: 11 年前关闭。 Possible Duplicate: Plain english explanation of Big O 我想这可能是类里面教的东西,但作为一个自学
假设我有两种算法: for (int i = 0; i 2)更长的时间给定的一些n - 其中n这种情况的发生实际上取决于所涉及的算法 - 对于您的具体示例, n 2)分别时间,您可能会看到: Θ(n)
这个问题在这里已经有了答案: Example of a factorial time algorithm O( n! ) (4 个回答) 6年前关闭。 我见过表示为 O(X!) 的 big-o 示例但
我是一名优秀的程序员,十分优秀!