estoy ejecutando el código Scala en un sistema de cuatro núcleos Core 2 de 32 bits:¿Por qué mis futuros scala no son más eficientes?
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)(_+_))
(Sí, lo hago sabemos que hay mucho formas más eficientes para sumar una serie de números enteros; es solo para darle algo al CPU).
Dependiendo de lo que se propuso a JOBS, el código se ejecuta en los siguientes momentos:
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
me sorprende que esto realmente no escala bien más allá de 2 de futuros "en juego". Hago un montón de código C++ multiproceso y no tengo dudas de que obtendría una buena escala de hasta 4 núcleos y vería> 390% de utilización de CPU si codificara este tipo de cosas con TBB de Intel o boost::threads
(sería mucho más prolijo de curso).
Entonces, ¿qué está pasando y cómo puedo obtener la escala de 4 núcleos que esperaría ver? ¿Está esto limitado por algo en Scala o JVM? Se me ocurre que realmente no sé "dónde" se ejecuta el futuro de scala ... es un hilo creado en el futuro, o "Futures" proporciona un grupo de hilos dedicado a ejecutarlos?
[Estoy usando la Scala 2.7.7 paquetes de Debian/Squeeze en un sistema de Lenny con el sol-java6 (6-20-0lennny1).]
Actualización:
Como se sugirió en la respuesta de Rex, grabé para evitar la creación de objetos.
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...
¡Esto fue mucho más rápido tuve que aumentar significativamente el recuento de iteraciones para ejecutar durante cualquier cantidad de tiempo! Los resultados son:
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
que es mucho más parecido a lo que yo espero ver (aunque el caso 3 puestos de trabajo es un poco extraño, con la realización de una tarea consistente un par de segundos antes de que los otros dos).
Empujar un poco más allá, en un hyperthreaded de cuatro núcleos i7 esta última versión con JOBS=8
logra un aumento de velocidad X4.4 vs JOBS = 1, con el uso de CPU 571%.
¡Estás impaciente, deseando el futuro hoy! En serio, Rex dio en el clavo, estás evaluando la recolección de basura, no la eficiencia de los futuros. –
Heh ... muy cierto.Cuando envié esta pregunta, no había estado usando Scala durante tanto tiempo, y probablemente era demasiado crédulo con respecto a la extrema exageración que la rodeaba. – timday
cuídate de volver a ejecutar la prueba con akka.dispatch.Future? –