3

そのため、宿題では、pi になるはずの関数の単純な統合を使用して、いくつかのスレッド化メカニズムで遊ぶことになっています。実装は、5000 億を超える間隔を処理することになっています。私の現在の実装では、2GB のヒープ サイズで最大約 5,000 万の for ループを処理します。ここで私の質問は、なぜ実装がそれほど多くのメモリを使用するのですか? (範囲を事前に作成する必要があるためだと思いますが、これは本当ですか?)そして、メモリ使用量を改善するにはどうすればよいですか?並列コレクションを使用することは可能ですか、それともこのような目的でスレッド プールを使用する必要がありますか?

注:次の実装で完全なクレジットを取得します。これは、私の知的好奇心と、scala をもっと流暢に使いこなせるようになるという私の夢のためです。

import scala.Math

object Pi {
 def calculate_pi(interval: Int): Double = {
    val start: Long = System.currentTimeMillis;
    var duration: Long = 0
    var x: Double = 2.0/interval
    var y: Double = 0.0
    var mypi: Double = 0.0

    (x until 1.0 by 1.0/interval).par.foreach(i => {
       y = 4.0/(1.0+x*x)
       mypi += (1.0/interval)*y
     })

   duration = (System.currentTimeMillis - start)
   println("scala calculate_pi\t" + interval + "\t" + duration + "ms\t" + mypi)
   return mypi
 }




object Main extends App {
  println("Please input the interval for the calculation")
  if(args.length < 1) { sys.exit }
  val interval = args(0).toInt 
  Pi.calculate_pi_seq(interval)
  Pi.calculate_pi(interval)
}
4

2 に答える 2

6

これはあらゆる種類の間違いです:

(x until 1.0 by 1.0/interval).par.foreach(i => {
   y = 4.0/(1.0+x*x)
   mypi += (1.0/interval)*y
 })

最初の問題は、 のすべての計算yが同一であることです:計算i中に使用していません。xは変化しないため、すべてのスレッドが同じ値を計算します。

そして、ここに 2 番目の問題があります。 mypi(およびy)を並列に計算しています。つまり、複数のスレッドが同時にmypi読み取りと書き込みを行っているということです。y

その中の問題を理解するために、1 つの実行を考えてみましょう。最初のスレッドが実行を開始し、計算yしてから読み取りy、 と としmypiます。その後、そのスレッドが一時停止し、他のすべてのスレッドが実行されます。最後に、そのスレッドが再開し、その計算結果を に書き込みますmypi。この場合、他のすべてのスレッドのすべての計算が無駄になります。これは、最終的な値がその 1 つのスレッドによって与えられたためです。

それは単純なケースでした。基本的に、これらの読み取りと書き込みのそれぞれで何が起こるかをまったく予測することはできませんmypi(yすべてのスレッドが同じ値を割り当てるため、より簡単です)。

そして、はい、 を呼び出すと.parNumericRangeその のすべての値を持つコレクションが作成されNumericRangeます。

于 2012-02-09T12:55:42.973 に答える
-3

基礎となるアプリケーションがわからないので、あなたが指摘したように、(たとえば)でメソッドを使用すると、事前にインスタンス化されることparを実験で学びました。Range

ただし、並列化を利用するためにコレクションのみを使用しているようです。言い換えれば、コレクション自体とは多少関係のないコードを計算するために - 値iは使用されていません。したがって、関心があるのは y と x の値だけなので、 foreach ループはかなり冗長です。単純な for ループで実行できることは、大量の作業のように思えるかもしれません。

そうは言っても、他のタイプの並列化は scala ではかなり簡単です。アクターの使用についてはどうですか?それらは軽量で非常にシンプルです。そうしないと、ワーカー スレッドまたは Java スレッドでさえうまくいく可能性があります。

于 2012-02-09T10:32:32.393 に答える