質問

この scala コードを 32 ビット クアッドコア Core2 システムで実行しています。

def job(i:Int,s:Int):Long = {
  val r=(i to 500000000 by s).map(_.toLong).foldLeft(0L)(_+_)
  println("Job "+i+" done")
  r
}

import scala.actors.Future
import scala.actors.Futures._

val JOBS=4

val jobs=(0 until JOBS).toList.map(i=>future {job(i,JOBS)})
println("Running...")
val results=jobs.map(f=>f())
println(results.foldLeft(0L)(_+_))

(はい、私は する あることを知ってください 多くの 一連の整数を合計するより効率的な方法。それは CPU に何かをさせるためだけです)。

JOBS の設定に応じて、コードは次の時間で実行されます。

JOBS=1 : 31.99user 0.84system 0:28.87elapsed 113%CPU
JOBS=2 : 27.71user 1.12system 0:14.74elapsed 195%CPU
JOBS=3 : 33.19user 0.39system 0:13.02elapsed 257%CPU
JOBS=4 : 49.08user 8.46system 0:22.71elapsed 253%CPU

これが実際には「プレイ中の」2 つの先物を超えて拡張できないことに驚いています。私は多くのマルチスレッド C++ コードを実行していますが、この種のコードを Intel の TBB または boost::threads (もちろん、かなり冗長になります)。

それで:何が起こっているのでしょうか?どうすれば期待通りの 4 コアに拡張できるでしょうか?これは scala または JVM の何かによって制限されますか?ところで、scala の先物が「どこ」で運用されているのか実際には分かりません...スレッドはFutureごとに生成されるのでしょうか、それとも「Futures」はそれらを実行するための専用のスレッドプールを提供しますか?

[私は、sun-java6 (6-20-0lennny1) を備えた Lenny システム上で Debian/Squeeze の scala 2.7.7 パッケージを使用しています。]

アップデート:

Rex の回答で示唆されているように、オブジェクトの作成を避けるために再コーディングしました。

def job(i:Long,s:Long):Long = {
  var t=0L
  var v=i
  while (v<=10000000000L) {
    t+=v
    v+=s
  }
  println("Job "+i+" done")
  t
}
// Rest as above...

これは非常に高速だったので、一定時間実行するには反復回数を大幅に増やす必要がありました。結果は次のとおりです。

JOBS=1: 28.39user 0.06system 0:29.25elapsed 97%CPU
JOBS=2: 28.46user 0.04system 0:14.95elapsed 190%CPU
JOBS=3: 24.66user 0.06system 0:10.26elapsed 240%CPU
JOBS=4: 28.32user 0.12system 0:07.85elapsed 362%CPU

これは私が期待していたものにかなり近いものです (ただし、3 つのジョブのケースは少し奇妙で、1 つのタスクが常に他の 2 つのタスクより数秒前に完了します)。

もう少し進めて、クアッドコア ハイパースレッド i7 の後者のバージョンでは、 JOBS=8 JOBS=1 と比較して 4.4 倍のスピードアップを実現し、CPU 使用率は 571% になります。

役に立ちましたか?

解決

私の推測では、ガベージ コレクターは追加自体よりも多くの作業を行っていると思われます。したがって、ガベージ コレクターが管理できる内容には制限があります。オブジェクトを作成しないもの (例:range/map/fold の代わりに while ループを使用します)。実際のアプリケーションが GC にこれほど大きな負荷をかける場合は、並列 GC オプションを試すこともできます。

他のヒント

試す

(i to 500000000 by s).view.map(_.toLong).foldLeft(0L)(_+_)

の応用 view (私が理解したように) は、単純なラッパーを提供することで繰り返しの反復とオブジェクトの作成を回避することになっています。

使用できることにも注意してください reduceLeft(_+_) 折りたたむ代わりに。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top