如何在Scala中优化理解和循环? [英] How to optimize for-comprehensions and loops in Scala?

查看:109
本文介绍了如何在Scala中优化理解和循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以Scala应该和Java一样快。我正在重新考察一下我最初在Java中处理过的Scala中的一些 Project Euler 问题。具体问题5:从1到20的所有数字均匀分布的最小正数是多少?

这是我的Java解决方案,需要0.7秒在我的机器上完成:

  public class P005_evenly_divisible implements Runnable {
final int t = 20;

public void run(){
int i = 10; (!isEvenlyDivisible(i,t)){
i + = 2;
}
System.out.println(i);


boolean isEvenlyDivisible(int a,int b){
for(int i = 2; i <= b; i ++){
if(a %i!= 0)
返回false;
}
返回true;

$ b $ public static void main(String [] args){
new P005_evenly_divisible()。run();




$ b $ p $这是我的直接翻译入斯卡拉, 103秒(147倍)!

  object P005_JavaStyle {
val t:Int = 20;
def run {
var i = 10
while(!isEvenlyDivisible(i,t))
i + = 2
println(i)
}
def isEvenlyDivisible(a:Int,b:Int):如果(a%i!= 0)
返回,则布尔= {
(i < - 2到b) false
return true

def main(args:Array [String]){
run
}
}

$ p
$ b

最后,这是我在函数式编程方面的尝试,它需要39秒(55倍的长度)

  object P005 extends App {
def isDivis(x:Int)=(1 to 20)forall {x%_ == 0}
def find n:Int):Int = if(isDivis(n))n else find(n + 2)
println(find(2))
}
/ pre>

在Windows上使用Scala 2.9.0.1  7 64位。我如何提高性能?难道我做错了什么?或者说Java只是快了很多?

解决方案

在这种情况下,问题是您从for表达式中返回。这反过来又被翻译成一个NonLocalReturnException的throw,它被封闭的方法所捕获。优化器可以消除foreach,但还不能消除throw / catch。扔/抓是昂贵的。但是由于这样的嵌套返回在Scala程序中并不多见,所以优化器还没有解决这个问题。有工作要改进优化器,希望能很快解决这个问题。


So Scala is supposed to be as fast as Java. I'm revisiting some Project Euler problems in Scala that I originally tackled in Java. Specifically Problem 5: "What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"

Here's my Java solution, which takes 0.7 seconds to complete on my machine:

public class P005_evenly_divisible implements Runnable{
    final int t = 20;

    public void run() {
        int i = 10;
        while(!isEvenlyDivisible(i, t)){
            i += 2;
        }
        System.out.println(i);
    }

    boolean isEvenlyDivisible(int a, int b){
        for (int i = 2; i <= b; i++) {
            if (a % i != 0) 
                return false;
        }
        return true;
    }

    public static void main(String[] args) {
        new P005_evenly_divisible().run();
    }
}

Here's my "direct translation" into Scala, which takes 103 seconds (147 times longer!)

object P005_JavaStyle {
    val t:Int = 20;
    def run {
        var i = 10
        while(!isEvenlyDivisible(i,t))
            i += 2
        println(i)
    }
    def isEvenlyDivisible(a:Int, b:Int):Boolean = {
        for (i <- 2 to b)
            if (a % i != 0)
                return false
        return true
    }
    def main(args : Array[String]) {
        run
    }
}

Finally here's my attempt at functional programming, which takes 39 seconds (55 times longer)

object P005 extends App{
    def isDivis(x:Int) = (1 to 20) forall {x % _ == 0}
    def find(n:Int):Int = if (isDivis(n)) n else find (n+2)
    println (find (2))
}

Using Scala 2.9.0.1 on Windows 7 64-bit. How do I improve performance? Am I doing something wrong? Or is Java just a lot faster?

解决方案

The problem in this particular case is that you return from within the for-expression. That in turn gets translated into a throw of a NonLocalReturnException, which is caught at the enclosing method. The optimizer can eliminate the foreach but cannot yet eliminate the throw/catch. And throw/catch is expensive. But since such nested returns are rare in Scala programs, the optimizer did not yet address this case. There is work going on to improve the optimizer which hopefully will solve this issue soon.

这篇关于如何在Scala中优化理解和循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆