Вопрос

Я запускаю этот Scala код на 32-битной системе Quad-Core 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)(_+_))

(Да я делать знаю, что есть много более эффективные способы суммы серии целых чисел; Это просто чтобы дать процессор что-нибудь сделать).

В зависимости от того, что я устанавливаю задания, код выполняется в следующем раз:

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 ++ и не сомневаюсь, что получаю хорошее масштабирование до 4 ядер и посмотреть> 390% загрузки процессора, если я закодировал эту вещь с TBB Intel или boost::threads (Это было бы значительно более добросовестно, конечно).

Итак: Что происходит и как я могу получить масштабирование до 4 ядер, я ожидаю увидеть? Это ограничено чем-то в Scala или JVM? Это происходит для меня, я на самом деле не знаю «где Futures Scala Futures ... это нить, порожденная в будущее, или делает« фьючерсы », предоставляют пул резьбы, посвященного их запуску?

Я использую пакеты SCALA 2.7.7 из Debian / Squeeze на Lenny System с Sun-Java6 (6-20-0Lennny1).

Обновлять:

Как предложено в ответе Рекса, я перекодировал, чтобы избежать создания объекта.

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 рабочих мест немного странно, с одной задачей последовательно завершают пару секунд до двух других).

Далее нажав его на четырехъядерную гипертертонную I7 последнюю версию с JOBS=8 Удовлетворяет Speedup Speedup VS X4.4 = 1, с использованием 571% CPU.

Это было полезно?

Решение

Я предполагаю, что сборщик мусора делает больше работы, чем сам добавление. Таким образом, вы ограничены тем, что может управлять сборщиком мусора. Попробуйте снова запустить тест с тем, что не создает никаких объектов (например, используйте цикл While вместо диапазона / карты / сгиба). Вы также можете играть с параллельными вариантами GC, если ваша реальная приложение будет сильно ударить GC.

Другие советы

Пытаться

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

Применение view Предполагается (как я понял ID), чтобы избежать повторной итерации и создания объекта, предоставляя простые обертки.

Обратите внимание, что вы можете использовать reduceLeft(_+_) вместо сгиба.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top