【问题标题】:Is MapReduce one form of Continuation-Passing Style (CPS)?MapReduce 是延续传递风格 (CPS) 的一种形式吗?
【发布时间】:2011-02-16 09:38:45
【问题描述】:

正如标题所说。我正在阅读Yet Another Language Geek: Continuation-Passing Style,我有点想知道 MapReduce 是否可以归类为一种形式的连续传递样式,即 CPS。

我也想知道 CPS 如何利用多台计算机来执行复杂的计算。也许 CPS 让Actor model 的工作变得更容易。

【问题讨论】:

  • 我认为我需要阅读并尝试了解更多,然后才能就该主题发表任何进一步的评论。

标签: mapreduce continuation-passing


【解决方案1】:

我会说他们是对立的。 MapReduce 显然适用于分布式,其中 Map 可以独立执行子任务。使用 CPS,您可以编写一个递归函数,其中每个调用都在等待一个较小的案例返回。

我认为 CPS 是 Guy Steele 在 The Future of Parallel: What's a Programmer to do? 上的演讲中描述为我们需要超越和忘却的编程技术之一

【讨论】:

  • 事实上,据我所知,Guy 在那次谈话中似乎没有提到 CPS。
【解决方案2】:

我不会这么说的。 MapReduce 确实执行用户定义的函数,但这些函数更好地称为“回调”。我认为 CPS 是一个非常抽象的概念,通常用于对更知名的概念(如函数、协程、回调和循环)的行为进行建模。一般不直接使用。

再一次,我可能将 CPS 与延续本身混淆了。我不是这两个方面的专家。

【讨论】:

  • Monadic 编程,例如一直在 Haskell 中完成,有时在 OCaml 等其他语言中完成,实际上是 CPS。所以它被直接使用,只是用不同的名字,经常和糖一起使用。
【解决方案3】:

CPS 和 MapReduce 都使用高阶函数。这意味着两者都涉及将函数作为参数的函数。

在 CPS 的情况下,您有一个函数(称为延续),其参数说明如何处理结果。通常(但不总是)延续使用一次。它是一个函数,它指定整个其余计算应该如何继续。这也使它成为一种连续的事情。通常你有一个执行线程,而延续指定它将如何继续。

对于 MapReduce,您提供的是多次使用的函数参数。这些参数函数并不真正代表整个其余的计算,而只是反复使用的小构建块。 “一遍又一遍”位通常可以分布在多台机器上,这使得这是一种并行的事情。

所以你看到一个共同点是对的。但其中一个并不是另一个的真正例子。

【讨论】:

    【解决方案4】:

    Map-reduce 是一种实现。允许您使用该实现的编码接口可以使用延续;这实际上是如何抽象框架和作业控制的问题。考虑 Hadoop 的声明性接口,如 Pig,或一般的声明性语言,如 SQL;接口下的机制可以有多种实现方式。

    例如,这是一个抽象的 Python map-reduce 实现:

    def mapper(input_tuples):
        "Return a generator of items with qualifying keys, keyed by item.key"
        # we are seeing a partition of input_tuples
        return (item.key, item) for (key, item) in input_items if key > 1)
    
    def reducer(input_tuples):
        "Return a generator of items with qualifying keys"
        # we are seeing a partition of input_tuples
        return (item for (key, item) in input_items if key != 'foo')
    
    def run_mapreduce(input_tuples):
        # partitioning is magically run across boxes
        mapper_inputs = partition(input_tuples)
        # each mapper is magically run on separate box
        mapper_outputs = (mapper(input) for input in mapper_inputs)
        # partitioning and sorting is magically run across boxes
        reducer_inputs = partition(
            sort(mapper_output for output in mapper_outputs))
        # each reducer is magically run on a separate box
        reducer_outputs = (reducer(input) for input in reducer_inputs)
    

    这是使用协程的相同实现,隐藏了更多神奇的抽象:

    def mapper_reducer(input_tuples):
        # we are seeing a partition of input_tuples
        # yield mapper output to caller, get reducer input
        reducer_input = yield (
            item.key, item) for (key, item) in input_items if key > 1)
        # we are seeing a partition of reducer_input tuples again, but the
        # caller of this continuation has partitioned and sorted
        # yield reducer output to caller
        yield (item for (key, item) in input_items if key != 'foo')
    

    【讨论】:

      猜你喜欢
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      • 2012-04-19
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 2015-12-20
      • 2012-04-27
      相关资源
      最近更新 更多