rdd = sc.parallelize(range(10))
accum = sc.accumulator(0)
def g(x):
global accum
accum += x
return x * x
a = rdd.map(g)
print(accum.value)
print(a.reduce(lambda x, y: x+y))
a.cache()
tmp = a.count()
print(accum.value)
print(rdd.reduce(lambda x, y: x+y))
tmp = a.count()
print(accum.value)
print(rdd.reduce(lambda x, y: x+y))
结果:
0
285
90
45
90
45
分析:
rdd = sc.parallelize(range(10))
accum = sc.accumulator(0)
def g(x):
global accum
accum += x
return x * x
a = rdd.map(g)
print(accum.value)
## 此时还没有任何action操作,没有开始计算,accum也没有在gx中被调用,所以accum=0
print(a.reduce(lambda x, y: x+y))
## reduce是一种action操作,此时开始真正计算,执行了gx,a变成
##[0,1,4,9,16,25,36,49,64,81],并且reduce求和=285
a.cache()
## 任何操作不改变cache,除非手动存入缓存。在执行cache之前,就算
##reduce真正计算,也没有真正改变a的指。将a存进cache之后,a的当
##前存储值才会从[0,1,2,3,4,5,6,7,8,9]变成[0,1,4,9,16,25,36,49,64,81]。
##但是注意cache是transformation操作,直到action之前,它其实并没有被真的写入cache
tmp = a.count()
print(accum.value)
## count 是一种action,开始真正计算,cache步骤也因此被激活,但在##此时,count重新调用了一次原始的gx,即a = rdd.map(g),所以又再次##被算了一次。即0+1+2+...+9=45之后,作为变量的accum又 +0+1+2+...+9=90。
print(rdd.reduce(lambda x, y: x+y))
## 虽然前面有a = rdd.map(g),但是这一步产生的是新rdd,对原来的rdd本身没有执行操作。还是[0,1,2...9]进行求和
tmp = a.count()
## 在cache中已经存储成[0,1,4...81]已经被激活过
print(accum.value)
## 此时不需要从头开始算,gx没有被再次触发,accum的值没有改变,还是90
print(rdd.reduce(lambda x, y: x+y))
## 同上
如果我们把cache这一步删除
rdd = sc.parallelize(range(10))
accum = sc.accumulator(0)
def g(x):
global accum
accum += x
return x * x
a = rdd.map(g)
print(accum.value)
print(a.reduce(lambda x, y: x+y))
#print(rdd.reduce(lambda x, y: x+y))
#a.cache()
#print(a.collect())
tmp = a.count()
#print(a.take(10))
print(accum.value)
#print(a.collect())
print(rdd.reduce(lambda x, y: x+y))
#a.cache()
#print(a.take(10))
tmp = a.count()
print(accum.value)
#print(a.take(10))
#print(a.collect())
print(rdd.reduce(lambda x, y: x+y))
0
285
90
45
135
45
这是因为没有cache过,在缓存中a始终是[0,1,…9]状态,每次进行action都要回头去找原始的数组,也就是a=rdd.map(g)这个产生的源头,也就意味着,accum每次都要被再算一次,于是有了后面的accum=135。