私はこの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コアまでのスケールアップが良好で、CPU使用率が390%を超えることは間違いありません。 )。
だから:何が起こっているのか、そしてどうすれば私が期待する4コアへのスケーリングを得ることができますか?これはscalaまたはJVMの何かによって制限されていますか?私は実際に「どこで」scalaの先物が実行されるのかわかりません...先物ごとに生成されるスレッドですか、それとも「Futures」はそれらを実行するための専用のスレッドプールを提供しますか?
[sun-java6(6-20-0lennny1)を搭載したLennyシステムでDebian/Squeezeのscala2.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=8JOBS = 1に対してx4.4のスピードアップが達成され、CPU使用率は571%になります。