避免“共享”的好方法?

发布于 2024-11-19 07:59:12 字数 663 浏览 2 评论 0原文

假设有人将这个简单的 Python 代码翻译成 Haskell:

def important_astrological_calculation(digits):
  # Get the first 1000000 digits of Pi!
  lucky_numbers = calculate_first_digits_of_pi(1000000)
  return digits in lucky_numbers

Haskell 版本:

importantAstrologicalCalculation digits =
  isInfixOf digits luckyNumbers
  where
    luckyNumbers = calculateFirstDigitsOfPi 1000000

在使用 Haskell 版本之后,程序员惊讶地发现他的 Haskell 版本“泄漏”了内存——在第一次调用他的函数之后,luckyNumbers 永远不会被释放。这很麻烦,因为该程序包含一些更相似的函数,并且所有这些函数消耗的内存都很大。

有没有一种简单而优雅的方法可以让程序“忘记”luckyNumbers

Suppose that someone would translate this simple Python code to Haskell:

def important_astrological_calculation(digits):
  # Get the first 1000000 digits of Pi!
  lucky_numbers = calculate_first_digits_of_pi(1000000)
  return digits in lucky_numbers

Haskell version:

importantAstrologicalCalculation digits =
  isInfixOf digits luckyNumbers
  where
    luckyNumbers = calculateFirstDigitsOfPi 1000000

After working with the Haskell version, the programmer is astonished to discover that his Haskell version "leaks" memory - after the first time his function is called, luckyNumbers never gets freed. That is troubling as the program includes some more similar functions and the memory consumed by all of them is significant.

Is there an easy and elegant way to make the program "forget" luckyNumbers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

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

评论(2

愛放△進行李 2024-11-26 07:59:12

在这种情况下,您的 pidigits 列表是一个常量(或“常量应用形式
),GHC 可能会将其浮出,计算一次,并在使用之间共享。如果没有对 CAF 的引用,它将被垃圾收集。

现在,一般来说,如果您想要重新计算某些内容,请将其转换为函数(例如通过添加虚拟 () 参数)并启用 -fno-full-laziness 。有关 CAF 的链接问题中的示例:如何制作CAF 不是 Haskell 中的 CAF?

In this case, your pidigits list is a constant (or "constant applicative form
), and GHC will probably float it out, calculate it once, and share amongst uses. If there are no references to the CAF, it will be garbage collected.

Now, in general, if you want something to be recalculated, turn it into a function (e.g. by adding a dummy () parameter) and enable -fno-full-laziness. Examples in the linked question on CAFs: How to make a CAF not a CAF in Haskell?

¢好甜 2024-11-26 07:59:12

解决此问题的三种方法(基于此博文

使用< code>INLINE pragmas

添加 {-# INLINE luckyNumbers #-} 和另一个 importantAstrologicalCalculation

这将使单独的调用彼此独立,每个调用都使用自己的 luckyNumbers 副本,该副本会迭代一次并立即由 GC 收集。

优点:

  • 需要对代码进行最少的更改

缺点:

  • 脆弱? kuribas 写道 写道“INLINE 并不保证内联,这取决于优化标志“
  • 机器代码重复。可能会创建更大且效率可能较低的可执行文件

使用 -fno-full-laziness GHC 标志

用虚拟 lambda 包裹 luckyNumbers 并使用 -fno-full-laziness< /code>:

{-# OPTIONS -fno-full-laziness #-}

luckyNumbers _ = calculateFirstDigitsOfPi 1000000

如果没有该标志,GHC 可能会注意到 luckyNumbers 中的表达式不使用其参数,因此它可能会将其浮出并共享它。

优点:

  • 没有机器代码重复:fibs 的实现是共享的,而不共享结果列表!

缺点:

  • 脆弱?我担心如果另一个模块使用 fibs 并且 GHC 决定内联它,并且第二个模块没有启用 -fno-full-laziness
  • 依赖于 GHC 标志, 那么这个解决方案可能会崩溃。这些可能比语言标准更容易改变
  • 需要修改我们的代码,包括所有 fib 的调用站点

功能化

Alonzo Church 著名地发现数据可以在函数中编码,我们可以使用它来避免创建可以共享的数据结构。

luckyNumbers 可以成为折叠 pi 数字的函数,而不是数据结构。

优点:

  • 坚固。毫无疑问,这将在面对各种编译器优化的情况下恢复工作。

缺点:

  • 更详细、
  • 非标准。我们不再使用标准列表,这些列表有大量支持它们的标准库函数,我们可能需要重新实现

Three ways to solve this (based on this blog post)

Using INLINE pragmas

Add {-# INLINE luckyNumbers #-} and another for importantAstrologicalCalculation.

This will make separate calls be independent from each other, each using their own copy of the luckyNumbers which is iterated once and is immediately collected by the GC.

Pros:

  • Require minimal changes to our code

Cons:

  • Fragile? kuribas wrote wrote that "INLINE doen’t guarantee inlining, and it depends on optimization flags"
  • Machine code duplication. May create larger and potentially less efficient executables

Using the -fno-full-laziness GHC flag

Wrap luckyNumbers with a dummy lambda and use -fno-full-laziness:

{-# OPTIONS -fno-full-laziness #-}

luckyNumbers _ = calculateFirstDigitsOfPi 1000000

Without the flag, GHC may notice that the expression in luckyNumbers doesn't use its parameter and so it may float it out and share it.

Pros:

  • No machine code duplication: the implementation of fibs is shared without the resulting list being shared!

Cons:

  • Fragile? I fear that this solution might break if another module uses fibs and GHC decides to inline it, and this second module didn't enable -fno-full-laziness
  • Relies on GHC flags. These might change more easily than the language standard does
  • Requires modification to our code including in all of fibs's call sites

Functionalization

Alonzo Church famously discovered that data can be encoded in functions, and we can use it to avoid creating data structures that could be shared.

luckyNumbers can be made to a function folding over the digits of pi rather than a data structure.

Pros:

  • Solid. Little doubt that this will resume working in the face of various compiler optimization

Cons:

  • More verbose
  • Non-standard. We're not using standard lists anymore, and those have a wealth of standard library functions supporting them which we may need to re-implement
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文