问题标签 [lazy-evaluation]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
haskell - 如何减少 Haskell 应用程序中的内存使用量?
我是函数式编程的新手,现在学习 Haskell。作为练习,我决定为一维线性扩散方程实施显式欧拉方法。虽然下面的代码可以正常工作,但我对它的性能并不满意。事实上,我关心的是内存消耗。我相信它与惰性评估有关,但无法弄清楚如何减少它的内存使用量。
该算法的思想非常简单,用命令式的术语来说清楚:它需要一个“数组”,并为每个内部点添加一个值,该值是由点本身和它的值的组合计算得出的。邻居。边界点是特殊情况。
所以,这是我的 Euler1D.hs 模块:
还有一个简单的 Main.hs:
为了比较,我还写了一个纯 C 实现。
现在,如果我尝试为足够大的数组运行 Haskell 实现n
,我有:
相比之下,C 版本快了近两个数量级:
编辑:这种比较并不公平,因为 Haskell 版本是使用分析标志编译的,而 C 不是。如果我编译两个程序都带有
-O2
和不带分析标志,我可以增加n
. 在这种情况下time ./eulerhs 1000000
需要 0m2.236s,而time ./eulerc 1000000
只需要 0m0.293s。所以问题仍然存在于所有优化中并且没有分析,它只是偏移。我还想指出,Haskell 程序的内存分配似乎与
n
. 这可能没问题。
但最糟糕的是内存要求。我的 Haskell 版本需要超过 100MB(我估计 C 中的最低限度是4MB)。我认为这可能是问题的根源。根据分析报告,该程序在 GC 上花费了 85% 的时间,并且
看到这么贵,我很makeu0
惊讶。我认为这是由于它的惰性评估(如果它的 thunk 保留在内存中直到结束)。stepEuler
我尝试了以下更改Main.hs
:
但没有注意到任何区别。我不知道如何减少stepEuler
. 所以,我的问题是:
- Haskell 有没有办法严格地构建列表/做列表推导?在这种情况下,让它保持懒惰没有任何好处。
- 在这种情况下,如何减少总体内存使用量?我想,我必须做一些严格的事情,但看不到是什么。换句话说,如果我必须放一些
seq
s和刘海,在哪里以及为什么? - 最后,最重要的是,识别这种昂贵结构的最佳策略是什么?
我确实在Real World Haskell中阅读了有关分析和优化的一章,但目前尚不清楚我如何准确地决定什么应该严格,什么不应该。
请原谅我这么长的帖子。
EDIT2:正如 A. Rex 在评论中所建议的那样,我尝试在 valgrind 中运行这两个程序。这就是我观察到的。对于 Haskell 程序(
n
=200000),它发现:malloc/free:33 次分配,30 次释放,分配了 84,109 字节。...检查了 55,712,980 个字节。
对于 C 程序(经过小修复):
malloc/free:2 次分配,2 次释放,分配了 3,200,000 字节。
因此,看起来虽然 Haskell 分配了小得多的内存块,但它经常这样做,并且由于垃圾收集的延迟,它们会累积并保留在内存中。所以,我还有一个问题:
- 是否有可能在 Haskell 中避免大量的小分配?基本上,要声明,我需要处理整个数据结构,而不仅仅是按需处理它的片段。
python - Django 形式的懒惰选择
我有一个这样的 Django my_forms.py:
每个选择例如(“轿车”、“轿车(15 辆汽车)”)。所以选择是由这个函数计算的。
我的问题是每次我只导入 my_forms.py 时都会执行选择函数。我认为这是由于 Django 声明其字段的方式:在类中但不在类方法中。这很好,但是我的views.py 导入了my_forms.py,因此无论使用哪个视图,都会在每个请求上完成选择查找。
我认为也许将choices=bodystyle_choices 不带括号会起作用,但我得到:
p>显然我可以使用缓存并将“import my_forms”放在所需的视图函数中,但这并没有改变重点:我的选择需要是懒惰的!
haskell - 严格评估的巧妙用途在哪里?
似乎有很多聪明的事情是用延迟评估的语言完成的,而在严格评估的环境中是无法完成的。例如 Haskell 中的无限列表或在一次 pass 中用树的最小值替换树中的每个元素。
有没有用严格评估的语言完成的聪明事情不能用懒惰评估的语言轻松完成的例子?
php - 如何让 PHP 避免延迟评估?
关于 PHP 评估布尔表达式的方式,我有一个有趣的问题。例如,当你有,
或者
PHP 首先检查$expression1
计算结果是否为true
. 如果不是这种情况,则$expression2
简单地跳过,以避免不必要的计算。在我正在编写的脚本中,我有:
$validator->valid("text")
即使第一个语句的计算结果为假,我也需要对第二个语句 ( ) 进行评估。我想问你是否有一些简单的方法可以强制 PHP 总是评估这两个语句。谢谢!
haskell - Haskell 脚本空间不足
我正在使用 Euler 项目自学 Haskell,但我在推理我的代码是如何被 Haskell 执行时遇到了一些麻烦。第二个问题让我计算所有偶数斐波那契数的总和,最高可达 400 万。我的脚本如下所示:
Hugs 给出错误“垃圾收集无法回收足够的空间”,我认为这意味着列表条目没有被释放,因为它们被foldr
.
我需要做什么来解决这个问题?我尝试编写一个使用累加器的尾递归(我认为)版本,但也无法让它工作。
hibernate - hibernate 懒惰的解决方案。这样对吗?
我正在使用以下方法来解决休眠中的延迟初始化问题。请告诉我它是否会起作用。由于某些原因,我必须在我的持久层强制执行我的事务。
在过滤器中我使用以下代码
这种方法对吗?能不能有什么问题。
hql - 在 HQL 执行期间将惰性设置为 true
在我们的应用程序中,我们根据应用程序需要将各种对象设置为lazy false。然而,在一个用例中,我们希望忽略 HBM 文件中的所有惰性设置,只获取目标对象。
所以问题是:有没有办法在 HQL 中指定只获取目标对象而不管 HBM 设置如何?
~斯里兰卡
c++ - 处理 C++ 类中的惰性计算
假设我有一堂课:
Whereinsert()
添加一个元素到easySet_
. difficultSet_
的成员根据 的成员而变化easySet_
。
我遇到的问题是,多次插入意味着difficultSet_
不断重新计算。所以我想difficultSet_
被懒惰地计算(即只有当difficultBegin()
, difficultEnd()
, ordifficultSize()
被调用时)。问题是,那我其实得把它difficultSet_
弄成一个mutable
,否则difficultSize()
不能对它进行操作。
所以现在我的班级声明看起来像
我觉得这是一个糟糕的设计。有没有更好的办法?
performance - Haskell 风格/效率
所以我正在研究一种懒惰地生成素数的方法,我想出了这三个定义,它们都以等效的方式工作 - 只是检查每个新整数是否在所有前面的素数中都有一个因子:
所以在我看来primes2
应该比 快一点primes1
,因为它避免了
f_ = f (const True)
对每个整数重新计算(我认为这需要按照我们迄今为止找到的素数数量的顺序工作),并且只在遇到新的时更新它主要。
仅从不科学的测试(take 1000
在 ghci 中运行)看来,它的运行速度似乎primes3
比primes2
.
我是否应该从中吸取教训,并假设如果我可以将函数表示为数组上的操作,我应该以后一种方式实现它以提高效率,还是这里发生了其他事情?
recursion - 有人可以向我解释这些 Haskell 函数吗?
我过去曾涉足过 Haskell,最近又认真研究了它,我正在阅读真实世界的 Haskell。他们所展示的一些例子,我还没有理解。这样的:
我不明白这是如何工作的,真正添加的 1 是什么?递归如何返回可以添加的东西?我不明白。
在这里我们有这个:
这是如何工作的,什么是 pre 真正被附加的?我不明白 case 表达式的结果是如何可以连接 pre 的。也许我只是需要有人详细解释这些功能的评估。我一定错过了一些非常重要的东西。
提前致谢!
编辑:我知道,这是复制粘贴失败。对不起。
编辑2:似乎我的困惑是这些功能实际上是/返回/我现在已经全部解决了。谢谢各位大神解答,终于成功了!我很感激!