Параллельный map/foreach в scala

Значок

Рекурсивная функция

procedure factorial(n)
  return (0<n) * factorial(n-1) | 1
end

я обманул немного отрицательных сторон разрешения для возврата 1. Если Вы хотите, чтобы он перестал работать, учитывая отрицательный аргумент, это немного менее кратко:

  return (0<n) * factorial(n-1) | (n=0 & 1)

Тогда

write(factorial(3))
write(factorial(-1))
write(factorial(20))

печать

6
2432902008176640000

Повторяющийся генератор

procedure factorials()
  local f,n
  f := 1; n := 0
  repeat suspend f *:= (n +:= 1)
end

Тогда

every write(factorials() \ 5)

печать

1
2
6
24
120

Для понимания этого: оценка направлена на цель и отслеживает в обратном порядке при отказе. Нет никакого булева типа и бинарных операторов, которые возвратили бы булевскую переменную на других языках, или перестать работать или возвратить их второй аргумент - за исключением |, который в контексте единственного значения возвращает его первый аргумент, если он успешно выполняется, иначе пробует его второй аргумент. (в контексте нескольких-значений это возвращается, его первый аргумент тогда его второй аргумент)

suspend похож yield на других языках, за исключением того, что генератор явно не называют многократно для возврата его результатов. Вместо этого every спрашивает его аргумент в пользу всех значений, но ничего не возвращает по умолчанию; это полезно с побочными эффектами (в этом вводе-выводе случая).

\ пределы количество значений, возвращенных генератором, который в случае [1 111] было бы бесконечно.

16
задан David Crawshaw 17 November 2009 в 21:31
поделиться

5 ответов

Мне нравится ответ Futures . Однако, хотя он будет выполняться одновременно, он также будет возвращать асинхронно, что, вероятно, не то, что вам нужно. Правильный подход будет следующим:

import scala.actors.Futures._

vals map { x => future { f(x) } } foreach { _() }
10
ответ дан 30 November 2019 в 15:51
поделиться

У меня возникли проблемы с использованием scala.actors.Futures в Scala 2.8 (когда я проверял, в нем были ошибки). Однако использование java libs напрямую сработало для меня:

final object Parallel {
  val cpus=java.lang.Runtime.getRuntime().availableProcessors
  import java.util.{Timer,TimerTask}
  def afterDelay(ms: Long)(op: =>Unit) = new Timer().schedule(new TimerTask {override def run = op},ms)
  def repeat(n: Int,f: Int=>Unit) = {
    import java.util.concurrent._
    val e=Executors.newCachedThreadPool //newFixedThreadPool(cpus+1)
    (0 until n).foreach(i=>e.execute(new Runnable {def run = f(i)}))
    e.shutdown
    e.awaitTermination(Math.MAX_LONG, TimeUnit.SECONDS)
  }
}
3
ответ дан 30 November 2019 в 15:51
поделиться

Последний выпуск Функциональной Java имеет некоторые функции параллелизма более высокого порядка, которые вы можете использовать.

import fjs.F._
import fj.control.parallel.Strategy._
import fj.control.parallel.ParModule._
import java.util.concurrent.Executors._

val pool = newCachedThreadPool
val par = parModule(executorStrategy[Unit](pool))

И затем ...

par.parMap(vals, f)

Не забудьте выключите пул .

2
ответ дан 30 November 2019 в 15:51
поделиться

Скалаз имеет parMap . Вы можете использовать его следующим образом:

import scalaz.Scalaz._
import scalaz.concurrent.Strategy.Naive

Это оснастит каждый функтор (включая Iterable ) методом parMap , так что вы можете просто сделать:

vals.parMap(f)

Вы также получите ] parFlatMap , parZipWith и т. д.

13
ответ дан 30 November 2019 в 15:51
поделиться

Я бы использовал scala.actors.Futures :

vals.foreach(t => scala.actors.Futures.future(f(t)))
2
ответ дан 30 November 2019 в 15:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: