Future
のデフォルトや parallel collection はデフォルトの実行コンテキスト(ExecutionContext
)を使って実行されます。
デフォルトの実行コンテキストは、実行機器のコア数分だけスレッドをプールします。
たとえば大きいリストを作って parallel collection で処理中のスレッド確認すると、コア数分あることがわかります。
scala> List.tabulate(100000)(identity).par.map(_ => Thread.currentThread.getId).distinct.size
res1: Int = 8 // このマシンは8コア
システムプロパティを設定することで、コア数ではなく望みのスレッド数に変更できます。
Scala 2.11.7 のこの辺 をみるとどうすればいいかわかります。
-
scala.concurrent.context.minThreads
-- 最小スレッド数。デフォルト 1。 -
scala.concurrent.context.numThreads
-- desired? スレッド数。デフォルトコア数。 -
scala.concurrent.context.maxThreads
-- 最大スレッド数。デフォルトコア数。
で min(max(minThread, numThread), maxThread)
がデフォルト実行コンテキストのスレッド数です。
さて、32スレッドまで上げてみましょう。
上の式から8コアのマシンで32スレッドにするには numThread および maxThread を32に設定すればいいことがわかります。 numThread の設定だけではダメなことに注意が必要ですね。
$ scala -Dscala.concurrent.context.numThreads=32 -Dscala.concurrent.context.maxThreads=32
scala> List.tabulate(1000000)(identity).par.map(_ => Thread.currentThread.getId).distinct.size
res1: Int = 32
ソースを見た人は気づいたと思いますが x4
などという形でコア数のn倍を表現できます。32のところは x4 としても (8コアのマシン上では) 同じです。
$ scala -Dscala.concurrent.context.numThreads=x4 -Dscala.concurrent.context.maxThreads=x4
最小スレッド数を 4 に設定(コア数がそれより大きい場合にはコア数に設定)するにはどうしたらいいでしょう?
minThread=4 に設定するだけだと、コア数が 4 より小さい場合、maxThread が 4 より小さくなるため、スレッド数は 4 より小さくなってしまいます。 minThread=4, maxThread=x4 に設定すれば、やりたいことが実現できそうです。
設定する際は min(max(minThread, numThread), maxThread)
を頭に入れて、うーんと唸ってから設定する必要がありそうですね!