From 82293958ed8ebaa56c8ce8f7a0467144e8adbecf Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 27 Oct 2011 21:57:37 -0400 Subject: [PATCH 1/6] Scala version, for speed comparison --- scala/.gitignore | 2 ++ scala/Bureaucrats.scala | 52 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 scala/.gitignore create mode 100644 scala/Bureaucrats.scala diff --git a/scala/.gitignore b/scala/.gitignore new file mode 100644 index 0000000..ab31b20 --- /dev/null +++ b/scala/.gitignore @@ -0,0 +1,2 @@ +*.class + diff --git a/scala/Bureaucrats.scala b/scala/Bureaucrats.scala new file mode 100644 index 0000000..e2c01aa --- /dev/null +++ b/scala/Bureaucrats.scala @@ -0,0 +1,52 @@ +object Bureaucrats { + val limit = 5000 + // result in seconds + def time(fn: => Unit): Double = { + val start = System.nanoTime + fn + (System.nanoTime - start) / 1.0E9 + } + def benchmark() { + val a = new Bureaucrats + var ticks = 0 + while(ticks < limit) { + a.go() + ticks += 1 + } + } + def main(args: Array[String]) { + while(true) + println(5000 / time(benchmark()) + " steps/second") + } +} + +class Bureaucrats { + val dim = 100 + val neighbors4 = List((1, 0), (-1, 0), (0, 1), (0, -1)) + val N = Array.fill(dim)(Array.fill(dim)(2)) + def rand = util.Random.nextInt(dim) + var total = 2 * dim * dim + def go() { + var active = List((rand, rand)) + N(active.head._1)(active.head._2) += 1 + total += 1 + while(active.nonEmpty) { + var nextActive = collection.mutable.ListBuffer[(Int, Int)]() + val overloaded = active.filter(coords => N(coords._1)(coords._2) > 3) + for((x, y) <- overloaded) { + N(x)(y) -= 4 + total += 4 + for((dx, dy) <- neighbors4) { + val x2 = x + dx + val y2 = y + dy + if(x2 >= 0 && x2 < dim && y2 >= 0 && y2 < dim) { + N(x2)(y2) += 1 + total += 1 + nextActive += ((x2, y2)) + } + } + } + active = nextActive.toList.distinct + } + } +} From 54183eb8b75fa19a8b2213db8a297093bb809fd1 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 28 Oct 2011 12:31:42 -0400 Subject: [PATCH 2/6] unroll loop for speed boost --- scala/Bureaucrats.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scala/Bureaucrats.scala b/scala/Bureaucrats.scala index e2c01aa..534b1ca 100644 --- a/scala/Bureaucrats.scala +++ b/scala/Bureaucrats.scala @@ -22,7 +22,6 @@ object Bureaucrats { class Bureaucrats { val dim = 100 - val neighbors4 = List((1, 0), (-1, 0), (0, 1), (0, -1)) val N = Array.fill(dim)(Array.fill(dim)(2)) def rand = util.Random.nextInt(dim) var total = 2 * dim * dim @@ -36,7 +35,7 @@ class Bureaucrats { for((x, y) <- overloaded) { N(x)(y) -= 4 total += 4 - for((dx, dy) <- neighbors4) { + def offLoadToNeighbor(dx: Int, dy: Int) = { val x2 = x + dx val y2 = y + dy if(x2 >= 0 && x2 < dim && y2 >= 0 && y2 < dim) { @@ -45,6 +44,10 @@ class Bureaucrats { nextActive += ((x2, y2)) } } + offLoadToNeighbor(1, 0) + offLoadToNeighbor(-1, 0) + offLoadToNeighbor(0, 1) + offLoadToNeighbor(0, -1) } active = nextActive.toList.distinct } From 813f05528c42ed6b5a217ac313a21738a3fcee89 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 28 Oct 2011 13:07:26 -0400 Subject: [PATCH 3/6] add plotting --- scala/Bureaucrats.scala | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scala/Bureaucrats.scala b/scala/Bureaucrats.scala index 534b1ca..fbf4762 100644 --- a/scala/Bureaucrats.scala +++ b/scala/Bureaucrats.scala @@ -1,5 +1,6 @@ object Bureaucrats { val limit = 5000 + var plot = collection.mutable.Buffer[Int]() // result in seconds def time(fn: => Unit): Double = { val start = System.nanoTime @@ -8,15 +9,19 @@ object Bureaucrats { } def benchmark() { val a = new Bureaucrats - var ticks = 0 - while(ticks < limit) { + while(plot.size < limit) { a.go() - ticks += 1 + plot :+= a.total } } def main(args: Array[String]) { - while(true) + while(true) { + plot.clear() println(5000 / time(benchmark()) + " steps/second") + for((x, ticks) <- plot.zipWithIndex) + if(ticks % 250 == 0) + println(Seq.fill((x - 20000) / 20)('*').mkString) + } } } From b885fe2e57b3da2713db781910be6d4c0f4a476c Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 28 Oct 2011 13:07:43 -0400 Subject: [PATCH 4/6] fix silly bug that was giving incorrect plot data --- scala/Bureaucrats.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scala/Bureaucrats.scala b/scala/Bureaucrats.scala index fbf4762..9af4817 100644 --- a/scala/Bureaucrats.scala +++ b/scala/Bureaucrats.scala @@ -39,7 +39,7 @@ class Bureaucrats { val overloaded = active.filter(coords => N(coords._1)(coords._2) > 3) for((x, y) <- overloaded) { N(x)(y) -= 4 - total += 4 + total -= 4 def offLoadToNeighbor(dx: Int, dy: Int) = { val x2 = x + dx val y2 = y + dy From e41e1047fb59ab110384d14ce685a2c1421d9e8b Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 28 Oct 2011 13:21:58 -0400 Subject: [PATCH 5/6] 3x speedup thanks to improved logic --- scala/Bureaucrats.scala | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/scala/Bureaucrats.scala b/scala/Bureaucrats.scala index 9af4817..5a9c1fc 100644 --- a/scala/Bureaucrats.scala +++ b/scala/Bureaucrats.scala @@ -31,30 +31,30 @@ class Bureaucrats { def rand = util.Random.nextInt(dim) var total = 2 * dim * dim def go() { - var active = List((rand, rand)) + var active: Seq[(Int, Int)] = List((rand, rand)) N(active.head._1)(active.head._2) += 1 total += 1 while(active.nonEmpty) { var nextActive = collection.mutable.ListBuffer[(Int, Int)]() - val overloaded = active.filter(coords => N(coords._1)(coords._2) > 3) - for((x, y) <- overloaded) { - N(x)(y) -= 4 - total -= 4 - def offLoadToNeighbor(dx: Int, dy: Int) = { - val x2 = x + dx - val y2 = y + dy - if(x2 >= 0 && x2 < dim && y2 >= 0 && y2 < dim) { - N(x2)(y2) += 1 - total += 1 - nextActive += ((x2, y2)) + for((x, y) <- active) + if(N(x)(y) > 3) { + N(x)(y) -= 4 + total -= 4 + def offLoadToNeighbor(dx: Int, dy: Int) = { + val x2 = x + dx + val y2 = y + dy + if(x2 >= 0 && x2 < dim && y2 >= 0 && y2 < dim) { + N(x2)(y2) += 1 + total += 1 + nextActive += ((x2, y2)) + } } + offLoadToNeighbor(1, 0) + offLoadToNeighbor(-1, 0) + offLoadToNeighbor(0, 1) + offLoadToNeighbor(0, -1) } - offLoadToNeighbor(1, 0) - offLoadToNeighbor(-1, 0) - offLoadToNeighbor(0, 1) - offLoadToNeighbor(0, -1) - } - active = nextActive.toList.distinct + active = nextActive } } } From a7621198538974105cfc8737db338133f62b9f6b Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 28 Oct 2011 13:24:01 -0400 Subject: [PATCH 6/6] add README for Scala version --- scala/README.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 scala/README.md diff --git a/scala/README.md b/scala/README.md new file mode 100644 index 0000000..6ef4b90 --- /dev/null +++ b/scala/README.md @@ -0,0 +1,37 @@ +# Bureaucrats model in Scala + +## Building + +Install Scala 2.9.1, then: +`scalac Bureaucrats.scala` + +## Running + +`scala Bureaucrats` + +## Results + +sample output on my iMac (2.8 GHz Intel Core i5): + +``` +************ +************************ +************************************* +************************************************* +************************************************************** +****************************************************** +************************************************************* +************************************************************ +********************************************************** +************************************************************** +************************************************************* +*************************************************************** +************************************************************* +*********************************************************** +**************************************************************** +**************************************************************** +************************************************************* +********************************************************** +********************************************************** +18016.39491937663 steps/second +```