2017-08-10 7 views
3

私は時間とメモリの両方でSparkの重い数学計算を開発しようとしています(両方ともO(n^2)まで)。私は、Iteratorを保持しているパーティションは、行ごとに1つのオブジェクトをインスタンス化することを強制しているので、大きな計算にはそれほど適切ではないことが分かっています(遅いですが、Iteratorです)。実際、最も単純なシナリオでは、たとえば、1行に1つのベクトルを保持します。しかし、BLASレベル3までの線形代数演算を改善するパフォーマンスを実際に向上させる可能性があるため、オブジェクトに対するJVMのオーバーヘッドとGCにかかるすべてのプレッシャーを知っているので、メモリにとっては有害です私はこのパラダイムで取り残されているベクトルで行列の代わりに行列)。非常に概略的には、ここで私が達成したいものです。ここでSpark:より良いメモリ管理のためにパーティション・イテレータをブレークしますか?

while (???) { // loop over some condition, doesn't really matter what 
    val matrix = ??? // an instance of a matrix 
    val broadMatrix = sparkContext.broadcast(matrix) 
    // rdd is an instance of RDD[Vector] that is already cached 
    rdd.mapPartition { 
     iter => 
      val matrixValue = broadMatrix.value() 
      iter.map (vector => matrixValue * vec) 
    } 
    // a bunch of other things relying on that result 
} 

が私の考えです:

  1. 上記のコードでは、私のrddがキャッシュされるように、その後、Iteratorを持つことは無用である、されていませんそれ?唯一の利点は、すべての行を同時にメモリに保持することではないためですが、ここでは計算されキャッシュされているので、すべての行がメモリに保持されます...もちろん、Sparkのインテリジェントなデータをシリアライズして圧縮するキャッシュ(ストレージレベルがMEMORY_ONLYでも...)

  2. もし私がrddに行があるのと同じくらい多くのJVMオブジェクトを持っているので、それが生成する唯一のものは大きなメモリオーバーヘッドですが、パーティションごとに1つのJVMオブジェクト。私は同じエグゼキュータ上にあるすべてのパーティションの共有メモリとして機能するscala objectを持つExecutorという1つのオブジェクトに絞り込むこともできます(これは私がSparkの復元力を維持したいと思うほど難しいかもしれません何らかの理由でパーティションを削除し、別のエグゼキュータに再表示する必要がある場合は、自分で処理するのではなく、関連するすべてのオブジェクトを単独で移動させます...)。

私の考え故に何かのように、行列を含んだものにvectorのこのrddを変換するために、次のようになります。

while (???) { // loop over some condition, doesn't really matter what 
    val matrix = ??? // an instance of a matrix 
    val broadMatrix = sparkContext.broadcast(matrix) 
    // rdd is an instance of RDD[Vector] that is already cached 
    rdd.mapPartition { 
     iter => 
      val matrixValue = broadMatrix.value() 
      // iter actually contains one single element which is the matrix containing all vectors stacked 
      // here we have a BLAS-3 operation 
      iter.map (matrix => matrixValue * matrix) 
    } 
    // a bunch of other things relying on that result 
} 

すでにこのジレンマに直面して誰ですか?あなたはこれと同じようにメモリ管理の事前使用を経験しましたか?

+0

Iteratorをnon-lazy collectionに変更すると、rddがキャッシュされていてもsparkが再びメモリを消費することが想像できます(2回)。私はあなたがちょうどいくつかのベンチマークを使用してより良いバージョンを試してみるべきだと思う –

+0

私はスパークが実際にメモリを2回消費すると想像し...私はそれを試して、私はより良いパフォーマンスがあるかどうかを見ていきます。私はベンチマークの結果をすぐに私はそれらを持って与えるでしょう! –

答えて

1

BLASレベル3までの線形代数演算を向上させるパフォーマンスを実際に向上させるかもしれないので、私はこのパラダイムで取り残されているベクトルによる行列ではなく行列による行列です。

Iteratorsを使用しても、Vectors、または各パーティションに複数の要素を使用することは一切ありません。必要に応じて、分割ごとに簡単にMatrixオブジェクトを作成することができます。

両方のメモリのための有害な、我々は、オブジェクトのためのJVMのオーバーヘッドとGC

私はこれよりもっと複雑であることを主張したいの上に置かれているすべての圧力を知っています。 Iteratorsを使用する理由は、メモリより大きなパーティションを処理できるためです。怠惰なIteratorsと小さなオブジェクトSparkは、部分的な結果をディスクに流し込み、ガベージコレクションのためにアクセスできるようにすることができます。これは、単一のラージオブジェクトを使用する場合には発生しません。私の経験から、Sparkは大きなオブジェクトを持つGCの問題の影響を受けやすくなっています。

説明に基づいて、私は、データを明示的に格納し、代わりにオフヒープメモリを使用してオブジェクトを明示的に初期化することを避けることが理にかなっていると思われます。これにより、GCが邪魔にならず、大きなオブジェクトを扱うことができます。しかしそれはグレードを支払うかもしれない上記の方法です。

関連する問題