Spark、単一のRDDを2つに最適に分割


10

特定のパラメーターに従ってグループに分割する必要がある大きなデータセットがあります。ジョブをできるだけ効率的に処理したい。そうするための2つの方法を想像することができます

オプション1-元のRDDからマップを作成してフィルターする

def customMapper(record):
    if passesSomeTest(record):
        return (1,record)
    else:
        return (0,record)

mappedRdd = rddIn.map(lambda x: customMapper(x))
rdd0 = mappedRdd.filter(lambda x: x[0]==0).cache()
rdd1 = mappedRdd.filter(lambda x: x[1]==1).cache()

オプション2-元のRDDを直接フィルターする

def customFilter(record):
    return passesSomeTest(record)

rdd0 = rddIn.filter(lambda x: customFilter(x)==False).cache()
rdd1 = rddIn.filter(customFilter).cache()

fistメソッドは、元のデータセットのすべてのレコードを3回テストする必要がありますが、2番目は通常の状況では2回のみ行う必要がありますが、sparkはシーンのグラフ作成の背後でいくらか実行するので、効果的に同じ方法で行われます。私の質問は次のとおりです:a。)1つの方法が他の方法より効率的であるか、またはスパークグラフの構築によってそれらが同等になるかb。)この分割を単一のパスで実行することは可能ですか


私も非常によく似た問題を抱えていて、解決策を見つけることができませんでした。しかし、sparkには「遅延評価」があり、実際に実行する必要があるものだけを実行でき、マップ、フィルター、および何でもできるものを組み合わせることができるため、実際に起こるかはこのコードからは明らかではありません。したがって、おそらくあなたが説明することは、単一のパスで発生する可能性があります。ただし、遅延評価メカニズムを十分に理解していません。実際、私は.cache()に気づきました。たぶん、1つの.cache()を実行して完全な結果を得る方法があるのでしょうか?
user3780968 2015年

回答:


9

まず、私はSparkのエキスパートではないことをお伝えします。過去数か月の間、私はそれをかなり使用してきましたが、私はそれを理解したと信じていますが、私は間違っているかもしれません。

だから、あなたの質問に答える:

a。)それらは同等ですが、見た目とは異なります。疑問に思っている場合、Sparkはグラフを最適化しませんが、customMapperどちらの場合も2回実行されます。これは、spark rdd1rdd22つの完全に異なるRDDであり、リーフから始めてボトムアップで変換グラフを作成するためです。したがって、オプション1は次のように変換されます。

rdd0 = rddIn.map(lambda x: customMapper(x)).filter(lambda x: x[0]==0).cache()
rdd1 = rddIn.map(lambda x: customMapper(x)).filter(lambda x: x[0]==1).cache()

あなたが言ったように、customMapperは2回実行されます(さらに、rddIn2回読み取られます。つまり、データベースから取得した場合、さらに遅くなる可能性があります)。

b。)方法があります。cache()適切な場所に移動する必要があります。

mappedRdd = rddIn.map(lambda x: customMapper(x)).cache()
rdd0 = mappedRdd.filter(lambda x: x[0]==0)
rdd1 = mappedRdd.filter(lambda x: x[0]==1)

これを行うことで、sparkにの部分的な結果を保存できることを伝えていmappedRddます。次に、rdd1との両方でこれらの部分的な結果を使用しますrdd2。スパークの観点からは、これは次と同等です。

mappedRdd = rddIn.map(lambda x: customMapper(x)).saveAsObjectFile('..')
# forget about everything
rdd0 = sc.objectFile('..').filter(lambda x: x[0]==0)
rdd1 = sc.objectFile('..').filter(lambda x: x[0]==1)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.