为使用视图的对象并行化(Scala)

为使用视图的对象并行化(Scala),scala,Scala,我对Scala很陌生!但是,我有以下工作解决方案,我想在上面使用par,看看我是否能做到: import scala.math object Problem4 { def isPalindrome(x: Int): Boolean = { val string = x.toString string.reverseIterator.sameElements(string.iterator) } def getPairs(minimum:

我对Scala很陌生!但是,我有以下工作解决方案,我想在上面使用
par
,看看我是否能做到:

import scala.math

object Problem4 {
    def isPalindrome(x: Int): Boolean = {
        val string = x.toString
        string.reverseIterator.sameElements(string.iterator)
    }

    def getPairs(minimum: Int, maximum: Int) = {
        for (i <- minimum to maximum view;
             j <- minimum to maximum view)
             yield (i, j)
    }

    def getAnswer(numberOfDigits: Int): Int = {
        val maximum = math.pow(10, numberOfDigits).toInt
        val minimum = math.pow(10, numberOfDigits - 1).toInt
        val products = for {
                           pair <- getPairs(minimum, maximum)
                           product = pair match { case (i, j) => i * j } 
                           if isPalindrome(product)
                       } yield product
        products.par.max
    }

    def main(args: Array[String]) {
        val answer = getAnswer(4)
        println("Problem 4 answer: %s".format(answer))
    }
} // object Problem4
此外,将
par
添加到
getPairs
调用会返回警告,仍然只使用我的一个处理器,并导致
java.lang.OutOfMemoryError:java堆空间
异常:

[info] Loading project definition from M:\programming\testdriveneuler\src\problem4\project
[info] Set current project to euler (in build file:/M:/programming/testdriveneuler/src/problem4/)
[info] Compiling 1 Scala source to M:\programming\testdriveneuler\src\problem4\target\scala-2.9.2\classes...
[warn] M:\programming\testdriveneuler\src\problem4\src\main\scala\Problem4.scala:39: `withFilter' method does not yet exist on scala.collection.parallel.ParSeq[((Int, Int), Int)], using `filter' method instead
[warn]                            pair <- getPairs(minimum, maximum).par
[warn]                                 ^
[warn] one warning found
[info]从M:\programming\testdriveneuler\src\problem4\project加载项目定义
[信息]将当前项目设置为euler(在生成文件中:/M:/programming/testdriveneuler/src/problem4/)
[信息]正在将1个Scala源代码编译为M:\programming\testdriveneuler\src\problem4\target\Scala-2.9.2\classes。。。
[警告]M:\programming\testdriveneuler\src\problem4\src\main\scala\problem4.scala:39:'withFilter'方法在scala.collection.parallel.ParSeq[((Int,Int),Int)]上尚不存在,请改用'filter'方法

[PARTION]

在GATEON调用中添加.PAR;

pair <- getPairs(min, max).par

<代码>配对> P>在调用GATONE时添加.PAR;
pair <- getPairs(min, max).par

pair太复杂了。它可以通过两个功能完成

def isPalindrome(x: Int) = x.toString sameElements x.toString.reverse

def products(min: Int, max: Int) = for { 
  x <- min to max par; 
  y <- min to max par; 
  if isPalindrome(x * y) 
} yield (x, y, x * y)

scala> products(100, 999).maxBy(_._3)
res0: (Int, Int, Int) = (913,993,906609)

太复杂了。它可以通过两个功能完成

def isPalindrome(x: Int) = x.toString sameElements x.toString.reverse

def products(min: Int, max: Int) = for { 
  x <- min to max par; 
  y <- min to max par; 
  if isPalindrome(x * y) 
} yield (x, y, x * y)

scala> products(100, 999).maxBy(_._3)
res0: (Int, Int, Int) = (913,993,906609)

您可以将其并行化,如下所示:

  def isPalindrome (n: Int) = n.toString == n.toString.reverse
  val R = 100 until 1000
  val xs = for (i <- R; j <- R) yield i * j
  val pals = xs.par filter isPalindrome
  println (pals max)
actors的好处在于,您可以使用命令式代码,并且仍然可以获得并行性。因此,将上面worker actor中的
calculate
方法替换为下面的方法,整个过程大约在1.0s内完成(改进了8倍)

我发现它在块大小更大的情况下工作得最快(尝试1000),并且确保您的工作人员至少与处理器数量相同

  def calculate(r1: Seq[Int], r2: Seq[Int]): Int = {
    def isPalindrome(x: Int) = {
      val s = x.toString
      s.reverseIterator.sameElements(s.iterator)
    }
    var max = 0
    // count down so that we don't have to check if palindrome so often
    var i = r1.last
    while (i >= r1.head) {
      // for some reason counting down here increases the run-time :/
      var j = r2.head
      while (j <= r2.last) {
        val r = i * j
        if (r > max && isPalindrome(r)) max = r
        j += 1
      }
      i -= 1
    }
    max
  } 
def计算(r1:Seq[Int],r2:Seq[Int]):Int={
def isPalindrome(x:Int)={
val s=x.toString
s、 reverseIterator.SameeElements(s.iterator)
}
var max=0
//倒计时,这样我们就不必经常检查回文
var i=r1.0
而(i>=r1.head){
//出于某种原因,此处倒计时会增加运行时间:/
var j=r2.0水头
而(j max&&isPalindrome(r))max=r
j+=1
}
i-=1
}
最大值
} 

您可以将其并行化,如下所示:

  def isPalindrome (n: Int) = n.toString == n.toString.reverse
  val R = 100 until 1000
  val xs = for (i <- R; j <- R) yield i * j
  val pals = xs.par filter isPalindrome
  println (pals max)
actors的好处在于,您可以使用命令式代码,并且仍然可以获得并行性。因此,将上面worker actor中的
calculate
方法替换为下面的方法,整个过程大约在1.0s内完成(改进了8倍)

我发现它在块大小更大的情况下工作得最快(尝试1000),并且确保您的工作人员至少与处理器数量相同

  def calculate(r1: Seq[Int], r2: Seq[Int]): Int = {
    def isPalindrome(x: Int) = {
      val s = x.toString
      s.reverseIterator.sameElements(s.iterator)
    }
    var max = 0
    // count down so that we don't have to check if palindrome so often
    var i = r1.last
    while (i >= r1.head) {
      // for some reason counting down here increases the run-time :/
      var j = r2.head
      while (j <= r2.last) {
        val r = i * j
        if (r > max && isPalindrome(r)) max = r
        j += 1
      }
      i -= 1
    }
    max
  } 
def计算(r1:Seq[Int],r2:Seq[Int]):Int={
def isPalindrome(x:Int)={
val s=x.toString
s、 reverseIterator.SameeElements(s.iterator)
}
var max=0
//倒计时,这样我们就不必经常检查回文
var i=r1.0
而(i>=r1.head){
//出于某种原因,此处倒计时会增加运行时间:/
var j=r2.0水头
而(j max&&isPalindrome(r))max=r
j+=1
}
i-=1
}
最大值
} 

我已经编辑了我的答案
getPairs
肯定会返回一个
视图
,将
par
添加到
getPairs
调用会抛出一个警告,不会并行化操作,并导致OutOfMemory“Java堆空间”异常。如您所建议的,省略最后一行会导致函数立即返回。这是否意味着for循环不执行计算,因为它使用视图使它变得懒惰
getPairs
肯定会返回一个
视图
,将
par
添加到
getPairs
调用会抛出一个警告,不会并行化操作,并导致OutOfMemory“Java堆空间”异常。如您所建议的,省略最后一行会导致函数立即返回。这是否意味着for循环不执行计算,因为它使用视图使其变得懒惰?您确定不打算对
for
循环使用
view
?在我的机器上运行
valxs
行会导致
java.lang.OutOfMemory:java堆空间
异常。我认为这是因为
vs
完全在内存中,而不是懒惰。请注意,正如在我的问题中所阐明的,我对4位数的Euler问题4感兴趣。@Asim上面的问题在我的机器上运行良好,只需使用默认的JVM设置。如果我尝试使用4位数字,我就会失去记忆。问题是,lazy和parallel并不能很好地结合在一起-如果你需要两者(并且实际上要更快),我认为这将比仅仅添加一个
.par
更复杂。你知道有多复杂吗?我对习惯于将惰性表达式和并行表达式结合起来非常感兴趣。如果我做得不好,我也做不到,但我认为
par
的目的是把它放在任何地方,让表达式神奇地并行化。@我的意思是,你必须进行自己的并行化,这不会太难(只需创建一个处理块的工人类,在自己的线程中启动几个)。这就是actor所做的,使用actor库可能更好。注意,4e6的解决方案并不懒惰。它只是通过在生成输出列表之前过滤来解决内存问题,这是一个好主意。哈哈,你忍不住了,是吗我非常喜欢Akka文档中的Pi示例,我也在其他地方重复使用它。谢谢你的编辑!您确定不打算对
for
循环使用
view
?在我的机器上运行
valxs
行会导致
java.lang.OutOfMemory:java堆空间
异常。我认为这是因为
vs
完全在内存中,而不是懒惰。请注意,正如我在问题中所阐明的,我对4位数字的Euler问题4感兴趣。@Asim上述方法在我的