并行化“MapReduce”中的“Reduce”

时间:2008-11-30 21:44:11

标签: multithreading optimization map multicore reduce

我理解Map如何轻松并行化 - 每台计算机/ CPU只能在阵列的一小部分上运行。

Reduce / foldl是否可并行化?似乎每个计算都取决于前一个计算。对于某些类型的函数,它是否可以并行化?

6 个答案:

答案 0 :(得分:14)

如果您的简化基础操作是关联*,您可以使用操作和地点的顺序。因此,在“聚集”阶段,你经常会有一个树状的结构,所以你可以在对数时间内以几次传递:

a  +  b  +  c  +  d
 \   /       \   /
 (a+b)       (c+d)
     \       /
   ((a+b)+(c+d))

代替(((a + b)+ c)+ d)

如果您的操作是可交换的,则可以进行进一步的优化,因为您可以按不同的顺序收集(例如,当这些操作是向量操作时,数据对齐可能很重要)

[*]你真正想要的数学运算,当然不是像浮点数那样的有效类型。

答案 1 :(得分:6)

是的,如果运营商是关联的。例如,您可以并行化对数字列表的求和:

step 1: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8
step 2:   3   +   7   +   11  +   15
step 3:       10      +       26
step 4:               36

这是因为(a + b)+ c = a +(b + c),即添加的顺序无关紧要。

答案 2 :(得分:3)

查看Hadoop中的合并阶段

http://wiki.apache.org/hadoop/HadoopMapReduce

答案 3 :(得分:1)

不确定您正在考虑哪种平台/语言,但您可以并行化这样的简化运算符:

// Original
result = null;
foreach(item in map) {
    result += item;
}

// Parallel
resultArray = array();
mapParts = map.split(numThreads);
foreach(thread) {
    result = null;
    foreach(item in mapParts[thread]) {
        result += item;
    }
    resultArray += result;    // Lock this!
}
waitForThreads();
reduce(resultArray);

如您所见,并行实现很容易递归。您将地图拆分,在其自己的线程中对每个部分进行操作,然后在完成这些线程后执行另一个减少以将这些部分组合在一起。

(这是Piotr Lesnick's answer背后的程序化推理。)

答案 4 :(得分:1)

从技术上讲,缩小与foldl(fold-left)不同,后者也可以描述为累积。

Jules给出的例子非常清楚地说明了减少操作:

step 1: 1 + 2 + 3 + 4 
step 2:   3   +   7   
step 3:       10      

请注意,在每一步中,结果都是一个数组,包括最终结果,它是一个项目的数组。

左侧折叠如下:

step 0: a = 0
step 1: a = a + 1 
step 2: a = a + 2 
step 3: a = a + 3
step 4: a = a + 4
step 5: a

现在显然这两者都产生相同的结果,但是当给定非关联运算符(如减法)时,foldl具有明确定义的结果,而reduce运算符则不具有。

答案 5 :(得分:0)

这取决于你的减少步骤。在MapReduce的Hadoop样式实现中,您的Reducer将被调用一次每个键,,其中所有行都与该键相关。

因此,例如,您的Mapper可能会接收大量无序的Web服务器日志,添加一些元数据(例如地理编码),并以cookie ID作为密钥发出[密钥,记录]对。然后,每个cookie ID将调用一次Reducer,并为该cookie提供所有数据,并可计算访问频率或每次访问查看的平均页面等汇总信息。或者您可以键入地理编码数据,并根据地理位置收集汇总统计数据。

即使您没有进行按键聚合分析 - 实际上,即使您在整个集合上计算某些东西 - 也许可以将计算分解成块,每个块都可以提供给Reducer