Python的map reduce与云计算中的map/reduce之间的关系是什么?

6

我刚开始学习Python,

有人知道Python(以及函数式编程语言)的函数 map() / reduce() 与分布式计算相关的MapReduce概念之间的关系吗?

2个回答

8
云计算中的map/reduce概念非常相似,但是改为并行工作。首先,每个数据对象都会通过一个函数进行处理,该函数将其map为一个新对象(通常是某种字典)。然后,在由map返回的对象对上调用reduce函数,直到只剩下一个为止。这就是map/reduce操作的结果。
一个重要的考虑因素是,由于并行化,reduce函数必须能够接收来自map函数以及之前reduce函数的对象。当你考虑并行化的方式时,这就更有意义了。许多机器将各自将其数据减少到单个对象,然后这些对象将被减少到最终输出。当然,如果有很多数据,这可能会发生在多个层面上。
下面是一个简单的示例,演示如何使用map/reduce框架来计算列表中的单词数:
list = ['a', 'foo', 'bar', 'foobar', 'foo', 'a', 'bar', 'bar', 'bar', 'bar', 'foo']
list2 = ['b', 'foo', 'foo', 'b', 'a', 'bar']

地图函数看起来会像这样:
def wordToDict(word):
  return {word: 1}

然后reduce函数看起来会像这样:

def countReduce(d1, d2):
  out = d1.copy()
  for key in d2: 
    if key in out:
      out[key] += d2[key]
    else:
      out[key] = d2[key]
  return out 

然后你可以像这样进行映射/归约:
reduce(countReduce, map(wordToDict, list + list2))

>>> {'a': 3, 'foobar': 1, 'b': 2, 'bar': 6, 'foo': 5}

但你也可以像这样做(这就是并行化会做的事情):
reduce(countReduce, [reduce(countReduce, map(wordToDict, list)), reduce(countReduce, map(wordToDict, list2))])

>>> {'a': 3, 'foobar': 1, 'b': 2, 'foo': 5, 'bar': 6}

最后一个示例是否应该明确递归调用子列表(即,在子列表的列表上映射lambda l: reduce(countReduce, map(wordToDict, *))? - Andrew Jaffe
@AndrewJaffe 不确定我理解你的评论。你能详细说明一下吗? - Aaron Dufour
[reduce(countReduce, map(wordToDict, list)), reduce(countReduce, map(wordToDict, list2))]map(lambda l: reduce(countReduce, map(wordToDict, l)), [list1, list2]) 是相同的,我认为后者更能体现操作的精髓。 - Andrew Jaffe
@AndrewJaffe 这并不完全做同样的事情。你需要在另一个reduce中包装它,所以它开始变得相当混乱。我会坚持我的方法,因为我认为这更明显些。 - Aaron Dufour

2
实际上,这些概念有所不同,通用名称有误导性。
在函数式编程中(Python 借用了这些函数):
- `map` 将某个函数应用于列表的所有元素,并返回一个新的列表。 - `reduce` 将某个函数应用于聚合某个列表中的所有值,以获得单个值。
在分布式计算 MapReduce 中:
- 我们始终使用键值对(好吧,只是一对)。 - `mapper` 获取一组键值对并生成另一组键值对(在此上下文中,“输入的键”失去了其语义)。 - `reducer` 获取一个键和与该键相应的值列表(来自 mapper 输出),并生成一些键和值的列表(“键”具有关键语义的唯一位置是 reducer 输入/mapper 输出:在传递给 reducer 之前,值按键分组)。 - 这里还可以使用分区器和组合器 :)
请注意,`mapper` 并非总是为每个输入对产生一个输出对,`reducer` 也不总是将每个(键,值列表)缩减到恰好一个输出对。Mapper 和 reducer 可以输出任何它们想要的内容。例如,`mapper` 可以用于过滤键值对 - 在这种情况下,它会为某些输入对生成输出对,并忽略其他输入对。对于每个 mapper/reducer 输入对(或其中一些输入对),产生多个输出对也不罕见。
但在大多数情况下,MapReduce 可以以类似或几乎相同的方式工作,如 `reduce(reduce_function, map(map_function, list))` - `mapper` 通常对每个输入执行某些计算,而 `reducer` 通常以某种方式聚合值列表。对于任何 `map_function` 和 `reduce_function`,都可以在 MapReduce 中表达这一点,但反过来则不行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接