Map-reduce 功能概述

Posted

技术标签:

【中文标题】Map-reduce 功能概述【英文标题】:Map-reduce functional outline 【发布时间】:2021-08-20 01:08:43 【问题描述】:

注意:这只是一个基本的编程问题,与“大数据处理”的 Hadoop 或 Map/Reduce 方法无关。

我们来个序列(1 2 3 4 5)

要将其映射到某个函数,比如square,我可以这样做:

(define (map function sequence)
  ; apply the function to each element in the sequence
  ; we do not reduce it, but return a list
  (if (null? sequence)
      nil
      (cons (function (car sequence))
            (map function (cdr sequence)))))

(map (lambda (x) (* x x)) '(1 2 3 4 5))
; (1 4 9 16 25)
>>> map(lambda x: x*x, [1,2,3,4,5])
# [1, 4, 9, 16, 25]
>>> def mymap(function, sequence):
      return [function(item) for item in sequence]

>>> mymap(lambda x: x*x, [1,2,3,4,5])
# [1, 4, 9, 16, 25]

对于像“map-reduce”这样的东西,如果我们假设一个给定的序列,它可能有大约三个步骤(我认为?):

map filter(订单可能与 map 交换,具体取决于正在执行的操作) reduce

这是对“map-reduce”范式的正确理解吗?它通常是不是一个看起来像这样的函数:

mapreduce(map_function, filter_function, reduce_function, sequence)

或者说组合在一起的时候一般是怎么处理的?

【问题讨论】:

我有点迷茫,究竟你在这里找什么? @gold_cy 非常熟悉上述数据/信号处理范例的人,可以对它通常如何完成进行结构性概述(我已经在方案或 python 中展示了一个示例......任何一种语言很好)。 【参考方案1】:

为了让您有直觉,我们需要(简要地)远离代码中的具体实现。 MapReduce(我不只是在谈论特定的实现)是关于问题的形状

假设我们有一个 xs 的线性数据结构(列表、数组等),我们有一个要应用于每个 xs 的变换函数,我们有一个聚合函数,可以表示为重复应用关联成对组合:

    xA           xB
     |           |
  xform(xA)   ​xform(xB)
       ​\       /
aggregator(xform(xA), xform(xB))
           ​|
         ​value

我们可以递归地将聚合器应用于整个列表/数组/xs 的任何内容:

    xA           xB               xC
     |           |                |
  xform(xA)   ​xform(xB)         xform(xC)
     |           |                |
     yA          yB               yC
       ​\       /                  |
aggregator(yA, yB)                |
           ​|                     /
         ​value                  /
           |                   /
          aggregator(value, yC)
                   |
              next_value

您要求使用 Python 或 Scheme,但如果我们使用类型,我发现这更容易考虑。转换器xform 接受一个类型为 A 的参数并返回一个 B:(x: A) -> B。聚合器aggregator 接受两个类型为 B 的参数并返回一个 B:(x: B, y: B) -> B

最简单且经常被过度使用的例子是平方和:

import functools

# Combiner
def add(a, b):
    return a + b

# Transformer
def square(a):
    return a * a

one_to_ten = range(1, 11)

functools.reduce(add, map(square, one_to_ten), 0)

不是很令人兴奋。但是,这与代码中没有真正显示的更直接的版本(但确实在图中显示)的区别在于,MapReduce 版本是完全可并行化的。您可以轻松地将其分块并在不同的线程、不同的盒子等上运行它的一部分。我们有变换,我们有组合功能,结合性意味着组合的顺序无关紧要。

现在,并非所有问题都可以通过这种方式进行分解,但令人惊讶的数量可以通过这种方式进行建模,并且它允许处理太大而无法在一个盒子上处理的数据集。现在显然,上面天真地编写的 Python 不能做到这一点,至少现在不能。但是没有理由一个足够聪明的编译器不能以这种方式发出字节码。

虽然我不知道 Scheme,但我知道 Clojure,它确实提供了 parallelized version of this exact thing:

(require '[clojure.core.reducers :as r])

(defn square [x] (* x x))

(r/fold + (pmap square (range 1 11)))

请注意,这并不完美:并行映射必须在(也是并行的)组合发生之前完成,但我们越来越接近了,这些是标准库调用。

【讨论】:

哇,很好的答案。感谢您的所有想法和时间。但是有一个问题:变量通常是如何完成的?例如xAxFormxs @David542 这并不重要。您可以选择所需的任何变量名称。问题是真的可以将您的问题建模为转换的递归关联成对组合(即幺半群)吗?

以上是关于Map-reduce 功能概述的主要内容,如果未能解决你的问题,请参考以下文章

map-reduce入门

pymongo map-reduce 无法根据查询工作

hadoop——配置eclipse下的map-reduce运行环境 1

什么是Map-Reduce

map-reduce 中不同组件/动作的执行顺序

Map-Reduce 大数据要点解说