我在http://en.wikipedia.org/wiki/MapReduce阅读了mapreduce,理解了如何在许多“文档”中获取“单词”计数的示例。但是我不明白以下几行:
因此,MapReduce框架将(键,值)对列表转换为值列表。此行为与函数式编程映射和reduce组合不同,后者接受任意值列表并返回一个值,该值组合了map返回的所有值。
有人可以再次详细说明差异(MapReduce框架VS地图和减少组合)?特别是,减少函数式编程有什么作用?
非常感谢。
答案 0 :(得分:8)
主要区别在于MapReduce显然具有可专利性。 (无法帮助自己,抱歉......)
更严重的是,正如我记得的那样,MapReduce论文描述了一种以大规模并行方式执行计算的方法。这种方法建立在多年前众所周知的map / reduce结构之上,但超出了分发数据等问题的范围。此外,对由上述函数操作和返回的数据结构施加了一些限制。 map
- 类似和reduce
- 计算的相似部分(数据来自键/值对列表),所以你可以说MapReduce是一个大规模并行友好的map&的专业化 reduce
组合。
至于维基百科对功能编程的map
/ reduce
构造中映射的函数的评论,每个输入产生一个值......好吧,确实如此,但这里有对所述值的类型没有任何限制。特别是,它可能是一个复杂的数据结构,可能是您再次应用map
/ reduce
转换的事物列表。回到“计算单词”示例,您可以很好地拥有一个函数,对于给定的文本部分,它会生成一个数据结构,将单词映射到文档(或文档块)上的出现计数map
,视情况而定)和reduce
结果。
事实上,这正是Phil Hagelberg在this article中所发生的事情。这是一个有趣且极其简短的例子,用于在Clojure中使用map
实现类似MapReduce字计数的计算,并且等同于reduce
((apply + (merge-with ...))
位 - merge-with
在clojure.core中以reduce
的形式实现。这个和维基百科示例之间的唯一区别是被计数的对象是URL而不是任意单词 - 除此之外,你有一个用map
和reduce
实现的计数单词算法,MapReduce风格,就在那里。它可能不完全符合MapReduce实例的原因是没有涉及的工作负载的复杂分布。这一切都发生在一个盒子上......虽然在盒子上提供了所有的CPU。
对于reduce
函数的深入处理 - 也称为fold
- 请参阅Graham Hutton的A tutorial on the universality and expressiveness of fold。它是基于Haskell的,但即使你不懂语言也应该是可读的,只要你愿意在你去的时候查找一两个Haskell ......就像++
= list concatenation,没有深深的哈斯克尔魔法。
答案 1 :(得分:1)
使用单词计数示例,原始功能map()
将采用一组文档,可选地分配该集合的子集,并且对于每个文档发出一个表示该数量的单个值文档中的单词(或特定单词的出现)。然后,功能reduce()
将为所有文档添加全局计数,一个用于每个文档。所以你得到一个总数(所有单词或特定单词)。
在MapReduce中,地图会为每个文档中的每个单词发出一个(单词,计数)对。然后,MapReduce reduce()
会将每个单词的计数加在每个文档中,而不会将它们混合到一个堆中。所以你得到一个与他们的计数配对的单词列表。
答案 2 :(得分:1)
MapReduce是一个围绕将计算分解为可并行化的映射器和缩减器的框架。它建立在熟悉的map和简化的基础之上 - 如果你可以构建你的任务,使它们可以由独立的映射器和reducer执行,那么你可以用一种利用MapReduce框架的方式编写它。
想象一个Python解释器,它识别可以独立计算的任务,并将它们运行到mapper或reducer节点。如果你写了
reduce(lambda x, y: x+y, map(int, ['1', '2', '3']))
或
sum([int(x) for x in ['1', '2', '3']])
您将在MapReduce框架中使用功能映射和reduce方法。使用当前的MapReduce框架,涉及到更多的管道,但它是相同的概念。