- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Actors/Futures
Fri, 2009-08-21, 15:22
Actors/Futures
Hi Folks,
I’ve been scouring the web and “Programming in Scala” for examples on how !! and futures are used within the Actors framework and have come up empty. Based on the examples I’ve found, I’ve worked up this example:
object ScalaFuturesApp {
def main(args : Array[String]) : Unit =
{
val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield f
val t = System.nanoTime
for(f <- futures) f()
//If this is is much greater than the number of processors, you probably
//aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
}
def f = future { Thread.sleep(1000) }
}
Unsurprisingly, it doesn’t execute the futures in parallel (I am not surprised because a) the docs state futures suspend execution in the current actor; and b) I don’t see any actors in this code). However, the few examples I’ve found do just this. For examples:
http://stackoverflow.com/questions/1149505/using-scala-actor-framework-as-fork-join-computation
http://www.nabble.com/Beginner-question-about-actors---concurrent-programming-td23506032.html
So then I tried the following based on the last link, only adding some actors in the mix. It appears that the yield f() statements never get executed. What I would like to see from this trivial example is a something where all of the futures execute in parallel. Something along the lines of taking about a second or two, dumping a bunch of “DONE” statements, then printing the total execution time.
object ScalaFuturesApp2 {
def main(args : Array[String]) : Unit =
{
val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors)
yield createActor !! "future"
val t = System.nanoTime
//This should block, but I don't think it does.
val res = for(f <- futures) yield f()
//If this is is much greater than the number of processors, you probably
//aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
}
def createActor = actor
{
loop {
react {
case "future" => reply(f)
}
}
}
def f = future { Thread.sleep(1000); println("DONE") }
}
Thanks for any help you can provide.
-Mark
I’ve been scouring the web and “Programming in Scala” for examples on how !! and futures are used within the Actors framework and have come up empty. Based on the examples I’ve found, I’ve worked up this example:
object ScalaFuturesApp {
def main(args : Array[String]) : Unit =
{
val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield f
val t = System.nanoTime
for(f <- futures) f()
//If this is is much greater than the number of processors, you probably
//aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
}
def f = future { Thread.sleep(1000) }
}
Unsurprisingly, it doesn’t execute the futures in parallel (I am not surprised because a) the docs state futures suspend execution in the current actor; and b) I don’t see any actors in this code). However, the few examples I’ve found do just this. For examples:
http://stackoverflow.com/questions/1149505/using-scala-actor-framework-as-fork-join-computation
http://www.nabble.com/Beginner-question-about-actors---concurrent-programming-td23506032.html
So then I tried the following based on the last link, only adding some actors in the mix. It appears that the yield f() statements never get executed. What I would like to see from this trivial example is a something where all of the futures execute in parallel. Something along the lines of taking about a second or two, dumping a bunch of “DONE” statements, then printing the total execution time.
object ScalaFuturesApp2 {
def main(args : Array[String]) : Unit =
{
val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors)
yield createActor !! "future"
val t = System.nanoTime
//This should block, but I don't think it does.
val res = for(f <- futures) yield f()
//If this is is much greater than the number of processors, you probably
//aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
}
def createActor = actor
{
loop {
react {
case "future" => reply(f)
}
}
}
def f = future { Thread.sleep(1000); println("DONE") }
}
Thanks for any help you can provide.
-Mark
Fri, 2009-08-21, 16:37
#2
Re: Actors/Futures
Re: [scala-user] Actors/Futures
On a related note, how is !! used? I can’t find an example of it being used anywhere. Would it be kind of like using an actor as a function generator?
Thanks,
Mark
On 8/21/09 9:09 AM, "Paul Phillips" <paulp [at] improving [dot] org" rel="nofollow">paulp@improving.org> wrote:
Thanks,
Mark
On 8/21/09 9:09 AM, "Paul Phillips" <paulp [at] improving [dot] org" rel="nofollow">paulp@improving.org> wrote:
On Fri, Aug 21, 2009 at 08:21:46AM -0600, Bastian, Mark wrote:
> val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield f
Range strikes again.
This isn't doing what you think it's doing. Try this:
for (i <- (0 to Runtime.getRuntime.availableProcessors).toList)
And here I will again predict that this behavior is going to change
eventually so we might as well deal with it now. (That's what I said
about the relative package problem way back when, so my skills as a
scala prophet are unquestionable!) It's simply too big a trap to leave
in a place where innocent newbies can get at it.
--
Paul Phillips | Simplicity and elegance are unpopular because
In Theory | they require hard work and discipline to achieve
Empiricist | and education to be appreciated.
ha! spill, pupil | -- Dijkstra
Fri, 2009-08-21, 16:47
#3
Re: Actors/Futures
Re: [scala-user] Actors/Futures
Thanks, that worked, but now I am confused about the issue you raised. If I execute the following two lines I get an identical result (both print 0-8).
for(i <- 0 to Runtime.getRuntime.availableProcessors) println(i)
for(i <- (0 to Runtime.getRuntime.availableProcessors).toList) println(i)
If I do this...
val a = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield i
println(a)
val b = for(i <- (0 to Runtime.getRuntime.availableProcessors).toList) yield i
println(b)
...I get:
RangeM(0, 1, 2, 3, 4, 5, 6, 7, 8) List(0, 1, 2, 3, 4, 5, 6, 7, 8)
So, in my OP example I can get either a List (good) or a Range (bad) of functions. I then do this: for(f <- futures) f(). Shouldn’t they both do the same thing as they are both interpreted as a sequence (<-at least that’s what I thought, but obviously this is not the case)? Is there somewhere I can read about and understand this issue? This seems like pretty unexpected behavior.
Thanks,
Mark
On 8/21/09 9:09 AM, "Paul Phillips" <paulp [at] improving [dot] org" rel="nofollow">paulp@improving.org> wrote:
for(i <- 0 to Runtime.getRuntime.availableProcessors) println(i)
for(i <- (0 to Runtime.getRuntime.availableProcessors).toList) println(i)
If I do this...
val a = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield i
println(a)
val b = for(i <- (0 to Runtime.getRuntime.availableProcessors).toList) yield i
println(b)
...I get:
RangeM(0, 1, 2, 3, 4, 5, 6, 7, 8) List(0, 1, 2, 3, 4, 5, 6, 7, 8)
So, in my OP example I can get either a List (good) or a Range (bad) of functions. I then do this: for(f <- futures) f(). Shouldn’t they both do the same thing as they are both interpreted as a sequence (<-at least that’s what I thought, but obviously this is not the case)? Is there somewhere I can read about and understand this issue? This seems like pretty unexpected behavior.
Thanks,
Mark
On 8/21/09 9:09 AM, "Paul Phillips" <paulp [at] improving [dot] org" rel="nofollow">paulp@improving.org> wrote:
On Fri, Aug 21, 2009 at 08:21:46AM -0600, Bastian, Mark wrote:
> val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield f
Range strikes again.
This isn't doing what you think it's doing. Try this:
for (i <- (0 to Runtime.getRuntime.availableProcessors).toList)
And here I will again predict that this behavior is going to change
eventually so we might as well deal with it now. (That's what I said
about the relative package problem way back when, so my skills as a
scala prophet are unquestionable!) It's simply too big a trap to leave
in a place where innocent newbies can get at it.
--
Paul Phillips | Simplicity and elegance are unpopular because
In Theory | they require hard work and discipline to achieve
Empiricist | and education to be appreciated.
ha! spill, pupil | -- Dijkstra
Fri, 2009-08-21, 16:57
#4
Re: Actors/Futures
Hi,
Paul is right about the range issue--the second `!!` send was only
executed after you received the first reply.
Otherwise, the use of `future` is redundant here--you already use `!!`
and let the actor do the computation. So, here it is:
object ScalaFuturesApp3 {
def main(args : Array[String]) {
val futures = for(i <- (1 to
Runtime.getRuntime.availableProcessors).toList)
yield createActor !! "future"
val t = System.nanoTime
//This blocks.
val res = for(f <- futures) {
f()
println((System.nanoTime - t) * 1.0E-9)
}
//If this is much greater than 1, you probably
//aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
}
def createActor = actor {
react {
case "future" =>
println("started")
Thread.sleep(1000)
println("DONE")
reply()
}
}
}
If you don't need messaging, you can use `future` as follows:
val futures = for (i <- (1 to
Runtime.getRuntime.availableProcessors).toList)
yield future { Thread.sleep(1000); println("DONE") }
val t = System.nanoTime
val res = for(f <- futures) {
f()
println((System.nanoTime - t) * 1.0E-9)
}
Cheers,
Philipp
Bastian, Mark wrote:
> Hi Folks,
>
> I’ve been scouring the web and “Programming in Scala” for examples on
> how !! and futures are used within the Actors framework and have come up
> empty. Based on the examples I’ve found, I’ve worked up this example:
>
> object ScalaFuturesApp {
> def main(args : Array[String]) : Unit =
> {
> val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors)
> yield f
> val t = System.nanoTime
> for(f <- futures) f()
> //If this is is much greater than the number of processors, you probably
> //aren't doing it right.
> println((System.nanoTime - t) * 1.0E-9)
> }
>
> def f = future { Thread.sleep(1000) }
> }
>
> Unsurprisingly, it doesn’t execute the futures in parallel (I am not
> surprised because a) the docs state futures suspend execution in the
> current actor; and b) I don’t see any actors in this code). However, the
> few examples I’ve found do just this. For examples:
> http://stackoverflow.com/questions/1149505/using-scala-actor-framework-a...
> http://www.nabble.com/Beginner-question-about-actors---concurrent-progra...
>
> So then I tried the following based on the last link, only adding some
> actors in the mix. It appears that the yield f() statements never get
> executed. What I would like to see from this trivial example is a
> something where all of the futures execute in parallel. Something along
> the lines of taking about a second or two, dumping a bunch of “DONE”
> statements, then printing the total execution time.
>
> object ScalaFuturesApp2 {
> def main(args : Array[String]) : Unit =
> {
> val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors)
> yield createActor !! "future"
> val t = System.nanoTime
> //This should block, but I don't think it does.
> val res = for(f <- futures) yield f()
> //If this is is much greater than the number of processors, you probably
> //aren't doing it right.
> println((System.nanoTime - t) * 1.0E-9)
> }
>
> def createActor = actor
> {
> loop {
> react {
> case "future" => reply(f)
> }
> }
> }
>
> def f = future { Thread.sleep(1000); println("DONE") }
> }
>
> Thanks for any help you can provide.
>
> -Mark
Fri, 2009-08-21, 16:57
#5
Re: Actors/Futures
Range is lazy. When you use for/yield on a range the expression in the yield is not evaluated, until needed. Like so
case class Foo(x : Int) {
println("created Foo" + x)
}
def test {
val foos = for(x <- 1 to 10) yield Foo(x)
println("done")
}
This program only prints "done", never creating any Foos
scala> test
done
This small change forces them to be evaluated
def test {
val foos = (for(x <- 1 to 10) yield Foo(x)).force // note the ".force"
println("done")
}
scala> test
created Foo1
created Foo2
created Foo3
created Foo4
created Foo5
created Foo6
created Foo7
created Foo8
created Foo9
created Foo10
done
In your case what's happening is that your futures aren't being created until you demand a value, at which point the future is created, started, and the current thread blocks waiting for the result. Add a "force"
On Fri, Aug 21, 2009 at 7:21 AM, Bastian, Mark <mbastia@sandia.gov> wrote:
case class Foo(x : Int) {
println("created Foo" + x)
}
def test {
val foos = for(x <- 1 to 10) yield Foo(x)
println("done")
}
This program only prints "done", never creating any Foos
scala> test
done
This small change forces them to be evaluated
def test {
val foos = (for(x <- 1 to 10) yield Foo(x)).force // note the ".force"
println("done")
}
scala> test
created Foo1
created Foo2
created Foo3
created Foo4
created Foo5
created Foo6
created Foo7
created Foo8
created Foo9
created Foo10
done
In your case what's happening is that your futures aren't being created until you demand a value, at which point the future is created, started, and the current thread blocks waiting for the result. Add a "force"
On Fri, Aug 21, 2009 at 7:21 AM, Bastian, Mark <mbastia@sandia.gov> wrote:
Hi Folks,
I’ve been scouring the web and “Programming in Scala” for examples on how !! and futures are used within the Actors framework and have come up empty. Based on the examples I’ve found, I’ve worked up this example:
object ScalaFuturesApp {
def main(args : Array[String]) : Unit =
{
val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield f
Fri, 2009-08-21, 17:07
#6
Re: Actors/Futures
Re: [scala-user] Actors/Futures
Thanks for all of the help! Let me offer up what I would consider the world’s simplest Fork-Join example based on your help:
object ForkJoinExample {
def main(args : Array[String]) : Unit =
{
//Fork
val futures = for(i <- (1 to Runtime.getRuntime.availableProcessors).toList)
yield future[Int] { Thread.sleep(1000); 1 }
val t = System.nanoTime
//Join
val numProcs = (for(f <- futures) yield f()).reduceRight(_+_)
//If this is is much greater than 1, you probably aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
println("You have " + numProcs + " processors.")
}
}
I apologize if I sound dense, but I am still not sure what the utility of the !! operator is given that the above example seems to pretty much do what you need with futures. Would you use !! to run the future on a different thread or maybe to have the actor be a producer of futures rather than your local thread?
Thanks,
Mark
On 8/21/09 9:29 AM, "Philipp Haller" <philipp [dot] haller [at] epfl [dot] ch" rel="nofollow">philipp.haller@epfl.ch> wrote:
object ForkJoinExample {
def main(args : Array[String]) : Unit =
{
//Fork
val futures = for(i <- (1 to Runtime.getRuntime.availableProcessors).toList)
yield future[Int] { Thread.sleep(1000); 1 }
val t = System.nanoTime
//Join
val numProcs = (for(f <- futures) yield f()).reduceRight(_+_)
//If this is is much greater than 1, you probably aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
println("You have " + numProcs + " processors.")
}
}
I apologize if I sound dense, but I am still not sure what the utility of the !! operator is given that the above example seems to pretty much do what you need with futures. Would you use !! to run the future on a different thread or maybe to have the actor be a producer of futures rather than your local thread?
Thanks,
Mark
On 8/21/09 9:29 AM, "Philipp Haller" <philipp [dot] haller [at] epfl [dot] ch" rel="nofollow">philipp.haller@epfl.ch> wrote:
Hi,
Paul is right about the range issue--the second `!!` send was only
executed after you received the first reply.
Otherwise, the use of `future` is redundant here--you already use `!!`
and let the actor do the computation. So, here it is:
object ScalaFuturesApp3 {
def main(args : Array[String]) {
val futures = for(i <- (1 to
Runtime.getRuntime.availableProcessors).toList)
yield createActor !! "future"
val t = System.nanoTime
//This blocks.
val res = for(f <- futures) {
f()
println((System.nanoTime - t) * 1.0E-9)
}
//If this is much greater than 1, you probably
//aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
}
def createActor = actor {
react {
case "future" =>
println("started")
Thread.sleep(1000)
println("DONE")
reply()
}
}
}
If you don't need messaging, you can use `future` as follows:
val futures = for (i <- (1 to
Runtime.getRuntime.availableProcessors).toList)
yield future { Thread.sleep(1000); println("DONE") }
val t = System.nanoTime
val res = for(f <- futures) {
f()
println((System.nanoTime - t) * 1.0E-9)
}
Cheers,
Philipp
Bastian, Mark wrote:
> Hi Folks,
>
> I’ve been scouring the web and “Programming in Scala” for examples on
> how !! and futures are used within the Actors framework and have come up
> empty. Based on the examples I’ve found, I’ve worked up this example:
>
> object ScalaFuturesApp {
> def main(args : Array[String]) : Unit =
> {
> val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors)
> yield f
> val t = System.nanoTime
> for(f <- futures) f()
> //If this is is much greater than the number of processors, you probably
> //aren't doing it right.
> println((System.nanoTime - t) * 1.0E-9)
> }
>
> def f = future { Thread.sleep(1000) }
> }
>
> Unsurprisingly, it doesn’t execute the futures in parallel (I am not
> surprised because a) the docs state futures suspend execution in the
> current actor; and b) I don’t see any actors in this code). However, the
> few examples I’ve found do just this. For examples:
> http://stackoverflow.com/questions/1149505/using-scala-actor-framework-as-fork-join-computation
> http://www.nabble.com/Beginner-question-about-actors---concurrent-programming-td23506032.html
>
> So then I tried the following based on the last link, only adding some
> actors in the mix. It appears that the yield f() statements never get
> executed. What I would like to see from this trivial example is a
> something where all of the futures execute in parallel. Something along
> the lines of taking about a second or two, dumping a bunch of “DONE”
> statements, then printing the total execution time.
>
> object ScalaFuturesApp2 {
> def main(args : Array[String]) : Unit =
> {
> val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors)
> yield createActor !! "future"
> val t = System.nanoTime
> //This should block, but I don't think it does.
> val res = for(f <- futures) yield f()
> //If this is is much greater than the number of processors, you probably
> //aren't doing it right.
> println((System.nanoTime - t) * 1.0E-9)
> }
>
> def createActor = actor
> {
> loop {
> react {
> case "future" => reply(f)
> }
> }
> }
>
> def f = future { Thread.sleep(1000); println("DONE") }
> }
>
> Thanks for any help you can provide.
>
> -Mark
Fri, 2009-08-21, 17:17
#7
Re: Actors/Futures
Re: [scala-user] Actors/Futures
Thanks, makes perfect sense (the reason for the behavior, not the design of the behavior itself. That’s um, unexpected.).
On 8/21/09 9:55 AM, "James Iry" <jamesiry [at] gmail [dot] com" rel="nofollow">jamesiry@gmail.com> wrote:
On 8/21/09 9:55 AM, "James Iry" <jamesiry [at] gmail [dot] com" rel="nofollow">jamesiry@gmail.com> wrote:
Range is lazy. When you use for/yield on a range the expression in the yield is not evaluated, until needed. Like so
case class Foo(x : Int) {
println("created Foo" + x)
}
def test {
val foos = for(x <- 1 to 10) yield Foo(x)
println("done")
}
This program only prints "done", never creating any Foos
scala> test
done
This small change forces them to be evaluated
def test {
val foos = (for(x <- 1 to 10) yield Foo(x)).force // note the ".force"
println("done")
}
scala> test
created Foo1
created Foo2
created Foo3
created Foo4
created Foo5
created Foo6
created Foo7
created Foo8
created Foo9
created Foo10
done
In your case what's happening is that your futures aren't being created until you demand a value, at which point the future is created, started, and the current thread blocks waiting for the result. Add a "force"
On Fri, Aug 21, 2009 at 7:21 AM, Bastian, Mark <mbastia [at] sandia [dot] gov" rel="nofollow">mbastia@sandia.gov> wrote:
Hi Folks,
I’ve been scouring the web and “Programming in Scala” for examples on how !! and futures are used within the Actors framework and have come up empty. Based on the examples I’ve found, I’ve worked up this example:
object ScalaFuturesApp {
def main(args : Array[String]) : Unit =
{
val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield f
Fri, 2009-08-21, 17:27
#8
Re: Actors/Futures
Futures are good for parallel bits of code that do fairly "pure" computation without interacting other than function argument/result boundaries, e.g fork/join style divide and conquer parallelism, map/reduce parallelism, etc.
Actors are good for concurrently operating bits of code that do need interact with the world and with each other.
!! allows you to send a message to an actor in the expectation of getting an answer back without blocking the current thread to wait for the answer. The current thread can continue to run until you fetch the result from the future. When you fetch the answer from the future, the current thread will block until the result is available.
!! is not absolutely necessary. The same result can be done entirely with asynch sends and receive/reacts. That just makes noiser code. You can also write "val result : Future[Any] = future(actor !? message)", but "val result : Future[Any] = actor !! message" is perhaps improvement enough to add the !! method.
On Fri, Aug 21, 2009 at 8:54 AM, Bastian, Mark <mbastia@sandia.gov> wrote:
!! allows you to send a message to an actor in the expectation of getting an answer back without blocking the current thread to wait for the answer. The current thread can continue to run until you fetch the result from the future. When you fetch the answer from the future, the current thread will block until the result is available.
!! is not absolutely necessary. The same result can be done entirely with asynch sends and receive/reacts. That just makes noiser code. You can also write "val result : Future[Any] = future(actor !? message)", but "val result : Future[Any] = actor !! message" is perhaps improvement enough to add the !! method.
On Fri, Aug 21, 2009 at 8:54 AM, Bastian, Mark <mbastia@sandia.gov> wrote:
Thanks for all of the help! Let me offer up what I would consider the world’s simplest Fork-Join example based on your help:
object ForkJoinExample {
def main(args : Array[String]) : Unit =
{
//Fork
val futures = for(i <- (1 to Runtime.getRuntime.availableProcessors).toList)
yield future[Int] { Thread.sleep(1000); 1 }
val t = System.nanoTime
//Join
val numProcs = (for(f <- futures) yield f()).reduceRight(_+_)
//If this is is much greater than 1, you probably aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
println("You have " + numProcs + " processors.")
}
}
I apologize if I sound dense, but I am still not sure what the utility of the !! operator is given that the above example seems to pretty much do what you need with futures. Would you use !! to run the future on a different thread or maybe to have the actor be a producer of futures rather than your local thread?
Thanks,
Mark
On 8/21/09 9:29 AM, "Philipp Haller" <philipp [dot] haller [at] epfl [dot] ch" target="_blank" rel="nofollow">philipp.haller@epfl.ch> wrote:
Hi,
Paul is right about the range issue--the second `!!` send was only
executed after you received the first reply.
Otherwise, the use of `future` is redundant here--you already use `!!`
and let the actor do the computation. So, here it is:
object ScalaFuturesApp3 {
def main(args : Array[String]) {
val futures = for(i <- (1 to
Runtime.getRuntime.availableProcessors).toList)
yield createActor !! "future"
val t = System.nanoTime
//This blocks.
val res = for(f <- futures) {
f()
println((System.nanoTime - t) * 1.0E-9)
}
//If this is much greater than 1, you probably
//aren't doing it right.
println((System.nanoTime - t) * 1.0E-9)
}
def createActor = actor {
react {
case "future" =>
println("started")
Thread.sleep(1000)
println("DONE")
reply()
}
}
}
If you don't need messaging, you can use `future` as follows:
val futures = for (i <- (1 to
Runtime.getRuntime.availableProcessors).toList)
yield future { Thread.sleep(1000); println("DONE") }
val t = System.nanoTime
val res = for(f <- futures) {
f()
println((System.nanoTime - t) * 1.0E-9)
}
Cheers,
Philipp
Bastian, Mark wrote:
> Hi Folks,
>
> I’ve been scouring the web and “Programming in Scala” for examples on
> how !! and futures are used within the Actors framework and have come up
> empty. Based on the examples I’ve found, I’ve worked up this example:
>
> object ScalaFuturesApp {
> def main(args : Array[String]) : Unit =
> {
> val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors)
> yield f
> val t = System.nanoTime
> for(f <- futures) f()
> //If this is is much greater than the number of processors, you probably
> //aren't doing it right.
> println((System.nanoTime - t) * 1.0E-9)
> }
>
> def f = future { Thread.sleep(1000) }
> }
>
> Unsurprisingly, it doesn’t execute the futures in parallel (I am not
> surprised because a) the docs state futures suspend execution in the
> current actor; and b) I don’t see any actors in this code). However, the
> few examples I’ve found do just this. For examples:
> http://stackoverflow.com/questions/1149505/using-scala-actor-framework-as-fork-join-computation
> http://www.nabble.com/Beginner-question-about-actors---concurrent-programming-td23506032.html
>
> So then I tried the following based on the last link, only adding some
> actors in the mix. It appears that the yield f() statements never get
> executed. What I would like to see from this trivial example is a
> something where all of the futures execute in parallel. Something along
> the lines of taking about a second or two, dumping a bunch of “DONE”
> statements, then printing the total execution time.
>
> object ScalaFuturesApp2 {
> def main(args : Array[String]) : Unit =
> {
> val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors)
> yield createActor !! "future"
> val t = System.nanoTime
> //This should block, but I don't think it does.
> val res = for(f <- futures) yield f()
> //If this is is much greater than the number of processors, you probably
> //aren't doing it right.
> println((System.nanoTime - t) * 1.0E-9)
> }
>
> def createActor = actor
> {
> loop {
> react {
> case "future" => reply(f)
> }
> }
> }
>
> def f = future { Thread.sleep(1000); println("DONE") }
> }
>
> Thanks for any help you can provide.
>
> -Mark
Fri, 2009-08-21, 17:27
#9
Re: Actors/Futures
The reason for the design is to allow work with huge ranges without computing a giant structure. Here's an example
scala> for (i <- 1 to 100000000) println(i)
1
2
3
...
100000000
scala> for (i <- (1 to 100000000).force) println(i)
java.lang.OutOfMemoryError: Java heap space
On Fri, Aug 21, 2009 at 9:12 AM, Bastian, Mark <mbastia@sandia.gov> wrote:
scala> for (i <- 1 to 100000000) println(i)
1
2
3
...
100000000
scala> for (i <- (1 to 100000000).force) println(i)
java.lang.OutOfMemoryError: Java heap space
On Fri, Aug 21, 2009 at 9:12 AM, Bastian, Mark <mbastia@sandia.gov> wrote:
Thanks, makes perfect sense (the reason for the behavior, not the design of the behavior itself. That’s um, unexpected.).
On 8/21/09 9:55 AM, "James Iry" <jamesiry [at] gmail [dot] com" target="_blank" rel="nofollow">jamesiry@gmail.com> wrote:
Range is lazy. When you use for/yield on a range the expression in the yield is not evaluated, until needed. Like so
case class Foo(x : Int) {
println("created Foo" + x)
}
def test {
val foos = for(x <- 1 to 10) yield Foo(x)
println("done")
}
This program only prints "done", never creating any Foos
scala> test
done
This small change forces them to be evaluated
def test {
val foos = (for(x <- 1 to 10) yield Foo(x)).force // note the ".force"
println("done")
}
scala> test
created Foo1
created Foo2
created Foo3
created Foo4
created Foo5
created Foo6
created Foo7
created Foo8
created Foo9
created Foo10
done
In your case what's happening is that your futures aren't being created until you demand a value, at which point the future is created, started, and the current thread blocks waiting for the result. Add a "force"
On Fri, Aug 21, 2009 at 7:21 AM, Bastian, Mark <mbastia [at] sandia [dot] gov" target="_blank" rel="nofollow">mbastia@sandia.gov> wrote:
Hi Folks,
I’ve been scouring the web and “Programming in Scala” for examples on how !! and futures are used within the Actors framework and have come up empty. Based on the examples I’ve found, I’ve worked up this example:
object ScalaFuturesApp {
def main(args : Array[String]) : Unit =
{
val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield f
On Fri, Aug 21, 2009 at 08:21:46AM -0600, Bastian, Mark wrote:
> val futures = for(i <- 0 to Runtime.getRuntime.availableProcessors) yield f
Range strikes again.
This isn't doing what you think it's doing. Try this:
for (i <- (0 to Runtime.getRuntime.availableProcessors).toList)
And here I will again predict that this behavior is going to change
eventually so we might as well deal with it now. (That's what I said
about the relative package problem way back when, so my skills as a
scala prophet are unquestionable!) It's simply too big a trap to leave
in a place where innocent newbies can get at it.