【问题标题】:Memoization Libraries for C?C 的记忆库?
【发布时间】:2011-08-29 07:53:40
【问题描述】:

对于我正在从事的项目,有许多州可以依靠计算来返回相同的结果(并且没有副作用)。显而易见的解决方案是对所有代价高昂的功能使用记忆。

我需要有处理多个状态的记忆(这样我就可以使一个缓存集无效而不使另一个缓存集无效)。有人知道这类事情的好 C 库吗? (请注意,它不能是 C++,我们说的是 C。)

我在 Python 中使用过一些很好的实现,它们使用装饰器能够灵活地记忆一堆不同的函数。我有点想知道是否有一个通用库可以用 C 做类似的事情(尽管可能使用显式函数包装而不是方便的语法)。我只是认为,当这是一个足够常见的问题时,必须为每个函数单独添加缓存是愚蠢的,必须有一些现成的解决方案。

我要寻找的特征如下:

  1. 可以缓存各种输入输出的函数
  2. 管理多个不同的缓存(因此您可以拥有短期和长期缓存)
  3. 具有很好的使缓存失效的功能
  4. 旨在用于包装函数,而不是更改现有函数

有人知道可以处理所有或大部分这些必要条件的 C 实现吗?

【问题讨论】:

  • 我不清楚这样的事情是如何工作的。像memoize(void*func, void*returnVal, int return size, ...) 这样的记忆包装器?显得复杂而脆弱。一堆预处理器骇客?你可以用这种东西做一些令人惊奇的事情,但它也往往很脆弱,可能成为维护的噩梦。但是,无论如何,这是个好问题。
  • 在 C++11 中完美转发会更好,但我可以想象它在 C 中通过向memoize() 提供类型描述符字典来完成一些性能损失。和 printf() 一样脆弱。
  • @Namey:人们一直在用 C 做记忆,但是一个通用的 C 库——就 C++ 如何具有模板或 Python 装饰器如何包装它而言是“通用的”——是痛苦的并且充满了陷阱。
  • @Fred:我想我的看法不同。每次想要记住一个单独的功能时都必须重新发明轮子,这样的痛苦和陷阱是否会减少?我宁愿在一个地方维护一件痛苦的事情,而不是分散在代码中各处的 1000 个临时实现。
  • @Namey:我的意思是对于该库的每次使用都“痛苦且充满陷阱”。就编写时而言,与编写通用库相比,添加“内部”记忆(使用实现知识)非常简单。重复的成本低于替代品的成本,恕我直言。

标签: c memoization


【解决方案1】:

为什么,就不能是 C++?

只是作为一个起点来看看这个记忆功能:

声明:

template<typename T, typename F>
auto Memoize(T key, F function) {
  static T memory_key = key;
  static auto memory = function(memory_key);
  if (memory_key != key) {
    memory_key = key;
    memory = function(memory_key);
  }

  return memory;
}

使用示例:

auto index = Memoize(value, IndexByLetter);

【讨论】:

    【解决方案2】:

    好的,因为没有 C 的记忆库,我正在寻找一种在代码库中记忆现有 C 函数的嵌入式解决方案,我制作了自己的小型记忆库,我将在 APL 2.0 下发布.希望人们会发现这很有用,并且不会在其他编译器上崩溃和烧毁。如果确实有问题,请在此处给我发消息,我会在有时间的时候进行研究(可能以几个月为增量来衡量)。

    这个库不是为了速度而构建的,但它可以工作并且已经过测试,以确保它使用起来相当简单,并且在我的测试中不会显示任何内存泄漏。从根本上说,这让我可以将记忆添加到类似于我在 Python 中习惯的装饰器模式的函数中。

    该库目前在 SourceForge 上,名称为 C-Memo Library。它带有一个小用户手册和几个用于通用散列的第 3 方许可库。如果位置发生变化,我会尝试更新此链接。我发现这对我的项目很有帮助,希望其他人会发现它对他们的项目有用。

    【讨论】:

    • 我使用了你的库,它可以工作!很好。我在 python 中编写了几乎完全相同的程序,它以 2m 50s 本机运行,而 7s 在 pypy 中运行。 C 程序运行时间为 46 秒。
    • 很高兴听到这个消息。我已经进行了几次清理,因此它可以与更多编译器一起愉快地工作。此外,这对 PyPy 来说是一个令人印象深刻的时期。他们一定在做一些有趣的事情来进行优化。
    • 是的,PyPy 已经由一个博士团队开发多年......所以我猜他们使用了一些非常核心的数学。我写的程序是为了解决一些 Project Euler 问题而写的,虽然写了这么久,我都忘了是哪一个了。
    • 是的,我知道。然而,与原始 Python 相比,获得 25 倍的加速仍然令人印象深刻。我记得 cPython 通常的加速比大约是 2-5 倍。
    【解决方案3】:

    memoization 几乎内置于 haskell 语言中。你可以call this functionality from c

    更新:
    我仍在学习函数式编程,但我知道记忆化在函数式编程中相当普遍,因为语言特性使它变得简单。我正在学习 f#。我不知道haskell,但它是我所知道的唯一可以与c交互的函数式语言。您也许可以找到另一种函数式编程语言,它以比 haskell 提供的更合适的方式与 c 交互。

    【讨论】:

    • 当然是一个有趣的评论。然而,开始在 Haskell 中包装 C 似乎有点矫枉过正。我还担心额外的 Haskell 生成的并非真正需要的 C 代码可能会影响性能。还有一个问题是我不清楚这种方法如何帮助记忆用 C 实现的函数。
    • 我更详细地更新了我的答案。它不是很有帮助,如果不是因为您的问题已经在这里 2 天没有答案,我根本不会提供这个答案。如果这对你来说是一个死胡同,我很抱歉,祝你好运。但是,如果它确实有效,那么我很高兴能提供帮助。
    • 嘿,至少感谢您的尝试。一个开箱即用的答案仍然至少是一个尝试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多