簡體   English   中英

如何在任務圖中更改全局變量值或使用Python在Apache Spark中減少

[英]How to change a global variable value inside a task map or reduce in Apache Spark using Python

我有以下代碼:

import sys
from pyspark import SparkContext

def mapper(array):
    aux = []
    array = str(array)
    aux = array.split(' | ')
    return {(aux[0][:-1],aux[1][:-1]): [(aux[0][1:],aux[1][1:])]}

def reducer(d1, d2):
    for k in d1.keys():
        if d2.has_key(k):
            d1[k] = d1[k] + d2[k]
            d2.pop(k)
    d1.update(d2)
    return d1 

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: bruijn <file>")
        exit(-1)
    sc = SparkContext(appName="Assembler")
    kd = sys.argv[1].lstrip('k').rstrip('mer.txt').split('d')
    k, d = int(kd[0]), int(kd[1])
    dic = sc.textFile(sys.argv[1],False).map(mapper).reduce(reducer)
    filepath = open('DeBruijn.txt', 'w')
    for key in sorted(dic):
        filepath.write(str(key) + ' -> ' + str(dic[key]) + '\n')
    filepath.close()        
    print('De Bruijn graph successfully generated!')
    sc.stop()

我想在main中創建一個名為vertexes的空列表,並使映射器在其中附加元素。 但是,使用關鍵字global不起作用。 我嘗試過使用累加器,但累加器的值不能在任務中獲取。

我想通過創建一個與列表一起使用的自定義類型的Accumulati來弄清楚如何做到這一點。 在我的代碼中,我所要做的就是插入以下導入並實現以下類:

from pyspark.accumulators import AccumulatorParam

class VectorAccumulatorParam(AccumulatorParam):
    def zero(self, value):
        return []
    def addInPlace(self, val1, val2):
        return val1 + [val2] if type(val2) != list else val2 #Had to do this check because without it the result would be a list with all the tuples inside of another list.

我的mapper函數將是這樣的:

def mapper(array):
    global vertexes
    aux = []
    array = str(array)
    aux = array.split(' | ')
    vertexes += (aux[0][:-1], aux[1][:-1]) #Adding a tuple into accumulator
    vertexes += (aux[0][1:], aux[1][1:]) #Adding a tuple into accumulator
    return {(aux[0][:-1],aux[1][:-1]): [(aux[0][1:],aux[1][1:])]

在調用mapper函數之前在main函數內部我創建了累加器:

vertexes = sc.accumulator([],VectorAccumulatorParam())

mapper / reducer函數調用后,我可以得到結果:

vertexes = list(set(vertexes.value))

Herio Sousa的VectorAccumulatorParam是一個好主意。 但是,您實際上可以使用內置類AddingAccumulatorParam,它與VectorAccumulatorParam基本相同。

在這里查看原始代碼https://github.com/apache/spark/blob/41afa16500e682475eaa80e31c0434b7ab66abcb/python/pyspark/accumulators.py#L197-L213

正如您所注意到的那樣,您無法將元素附加到映射器內(或者您可以將元素附加到映射器內部,但更改不會推廣到任何其他映射器或您的主函數)。 正如您已經注意到累加器允許您附加元素,但是它們只能在驅動程序中讀取並寫入執行程序中。 如果你想要不同的密鑰,你可以讓另一個映射器輸出密鑰並在其上調用distinct。 您可能還想查看reduceByKey而不是您正在使用的reduce。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM