1.Scalaからのクロージャを理解する
クロージャは、戻り値が関数の外部で宣言された1つ以上の変数に依存する関数です。クロージャは一般に、関数内のローカル変数にアクセスできる別の関数と単純に考えることができます。
次の無名関数など:
val multiplier = (i:Int) => i * 10
関数本体には変数iがあり、これは関数のパラメーターとして機能します。以下の別のコードとして:
val multiplier = (i:Int) => i * factor
にmultiplier
は2つの変数があります:iとfactor。iがパラメータの関数の形式である場合、multiplier
関数は呼び出され、iには新しい値が与えられます。ただし、factorは仮パラメーターではなく、自由変数です。次のコードについて考えてみます。
var factor = 3 val multiplier = (i:Int) => i * factor
ここではfactor
、関数の外部で定義されている自由変数を紹介します。
このようにmultiplier
「クロージャ」として定義された関数変数は、関数定義の外部の変数を参照するため、このプロセス関数の定義は、自由変数をキャプチャして閉じた関数を形成することです。
完全な例:
object Test {
def main(args: Array[String]) {
println( "muliplier(1) value = " + multiplier(1) )
println( "muliplier(2) value = " + multiplier(2) )
}
var factor = 3
val multiplier = (i:Int) => i * factor
}
2.Sparkのクロージャの理解
まず、次のコードを見てください。
val data=Array(1, 2, 3, 4, 5)
var counter = 0
var rdd = sc.parallelize(data)
// ???? 这样做会怎么样
rdd.foreach(x => counter += x)
println("Counter value: " + counter)
最初に確認する必要があるのは、上記の出力の結果が0であり、parkがRDD操作の処理をタスクに分解し、各タスクがExecutor
実行されることです。実行前に、Sparkはタスクの終了を計算します。クロージャはExecutor
、RDD(この場合はforeach())で計算を実行するときに表示する必要がある変数とメソッドです。クロージャーはシリアル化されて各エグゼキューターに送信されますが、コピーはエグゼキューターに送信されるため、ドライバーの出力はそのままcounter
です。グローバルを更新する場合は、アキュムレーターをspark-streaming
使用しupdateStateByKey
てパブリックステータスを更新します。
さらに、Sparkのクロージャには他の機能があります。
1.ドライバーからエグゼキューターに送信された不要なグローバル変数をクリアし、有用な変数情報のみをエグゼキューターにコピーします
2.Executorに送信されるデータがシリアル化されたデータであることを確認します
たとえば、DataSetを使用する場合、ケースクラスの定義はメソッド内ではなくクラスの下にある必要があります。構文に問題がない場合でも、json4sを使用してシリアル化した場合implicit val formats = DefaultFormats
は、インポートをそれ以外の場合は、他の目的で使用しない場合でも、フォーマットシーケンスを個別に指定する必要があります。
3.まとめ
クロージャは、Sparkのライフサイクル全体のどこにでも表示Driver
されます。たとえば、上記からコピーされたすべてのデータは、シリアル化+クロージャする必要がありますExecutor
。
Wu Xie、Xiao San Ye、バックグラウンドの小さな新人、ビッグデータ、人工知能。もっと注意してください