From 971d1e8ac72b6d4fb76874d04a6a4873983f41e1 Mon Sep 17 00:00:00 2001 From: Tom Lin Date: Sat, 7 Oct 2023 12:10:08 +0100 Subject: [PATCH] Add init/read timing for Scala --- src/scala/scala-stream/.bsp/sbt.json | 1 - src/scala/scala-stream/.gitignore | 1 + src/scala/scala-stream/.scalafmt.conf | 2 +- src/scala/scala-stream/build.sbt | 13 ++-- .../scala-stream/project/build.properties | 2 +- src/scala/scala-stream/project/plugins.sbt | 6 +- .../main/scala/scalastream/ScalaStream.scala | 63 ++++++++++++++----- 7 files changed, 63 insertions(+), 25 deletions(-) delete mode 100644 src/scala/scala-stream/.bsp/sbt.json diff --git a/src/scala/scala-stream/.bsp/sbt.json b/src/scala/scala-stream/.bsp/sbt.json deleted file mode 100644 index 2e1edb1..0000000 --- a/src/scala/scala-stream/.bsp/sbt.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"sbt","version":"1.5.2","bspVersion":"2.0.0-M5","languages":["scala"],"argv":["/usr/lib/jvm/java-11-openjdk-11.0.11.0.9-2.fc33.x86_64/bin/java","-Xms100m","-Xmx100m","-classpath","/home/tom/.local/share/JetBrains/Toolbox/apps/IDEA-U/ch-0/211.7142.45.plugins/Scala/launcher/sbt-launch.jar","xsbt.boot.Boot","-bsp","--sbt-launch-jar=/home/tom/.local/share/JetBrains/Toolbox/apps/IDEA-U/ch-0/211.7142.45.plugins/Scala/launcher/sbt-launch.jar"]} \ No newline at end of file diff --git a/src/scala/scala-stream/.gitignore b/src/scala/scala-stream/.gitignore index 2f7896d..ee5cda2 100644 --- a/src/scala/scala-stream/.gitignore +++ b/src/scala/scala-stream/.gitignore @@ -1 +1,2 @@ target/ +.bsp/ diff --git a/src/scala/scala-stream/.scalafmt.conf b/src/scala/scala-stream/.scalafmt.conf index 8c7d0c8..5d87df3 100644 --- a/src/scala/scala-stream/.scalafmt.conf +++ b/src/scala/scala-stream/.scalafmt.conf @@ -1,4 +1,4 @@ -version = "3.0.0-RC2" +version = "3.7.14" runner.dialect = scala3 style = defaultWithAlign diff --git a/src/scala/scala-stream/build.sbt b/src/scala/scala-stream/build.sbt index 49164f6..b13fda3 100644 --- a/src/scala/scala-stream/build.sbt +++ b/src/scala/scala-stream/build.sbt @@ -3,7 +3,7 @@ lazy val mainCls = Some("scalastream.App") lazy val root = (project in file(".")) .enablePlugins(NativeImagePlugin) .settings( - scalaVersion := "3.0.0", + scalaVersion := "3.3.1", version := "4.0", organization := "uk.ac.bristol.uob-hpc", organizationName := "University of Bristol", @@ -11,6 +11,11 @@ lazy val root = (project in file(".")) assembly / mainClass := mainCls, scalacOptions ~= filterConsoleScalacOptions, assembly / assemblyJarName := "scala-stream.jar", + assembly / assemblyMergeStrategy := { + case PathList("module-info.class") => MergeStrategy.discard + case PathList("META-INF", "versions", xs @ _, "module-info.class") => MergeStrategy.discard + case x => (ThisBuild / assemblyMergeStrategy).value(x) + }, nativeImageOptions := Seq( "--no-fallback", "-H:ReflectionConfigurationFiles=../../reflect-config.json" @@ -22,8 +27,8 @@ lazy val root = (project in file(".")) // Lazy val implementation in Scala 3 triggers an exception in nativeImage, use 2_13 for arg parsing for now otherwise we can't get to the benchmarking part ("com.github.scopt" %% "scopt" % "4.0.1").cross(CrossVersion.for3Use2_13), // par also uses lazy val at some point, so it doesn't work in nativeImage - "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.3", - "net.openhft" % "affinity" % "3.21ea1", - "org.slf4j" % "slf4j-simple" % "1.7.30" // for affinity + "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.4", + "net.openhft" % "affinity" % "3.23.2", + "org.slf4j" % "slf4j-simple" % "2.0.5" // for affinity ) ) diff --git a/src/scala/scala-stream/project/build.properties b/src/scala/scala-stream/project/build.properties index 19479ba..875b706 100644 --- a/src/scala/scala-stream/project/build.properties +++ b/src/scala/scala-stream/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.2 +sbt.version=1.9.2 diff --git a/src/scala/scala-stream/project/plugins.sbt b/src/scala/scala-stream/project/plugins.sbt index 2c82902..35a00f0 100644 --- a/src/scala/scala-stream/project/plugins.sbt +++ b/src/scala/scala-stream/project/plugins.sbt @@ -1,6 +1,6 @@ addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.5.3") -addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.17") +addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.20") addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.3.0") -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.3") addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.27") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.3") diff --git a/src/scala/scala-stream/src/main/scala/scalastream/ScalaStream.scala b/src/scala/scala-stream/src/main/scala/scalastream/ScalaStream.scala index 9c011a6..888ba7c 100644 --- a/src/scala/scala-stream/src/main/scala/scalastream/ScalaStream.scala +++ b/src/scala/scala-stream/src/main/scala/scalastream/ScalaStream.scala @@ -14,6 +14,7 @@ transparent trait ScalaStream[@specialized(Float, Double) A]: def config: Config[A] def initArrays(): Unit + def readArrays(): Unit = () def copy(): Unit def mul(): Unit def add(): Unit @@ -27,6 +28,8 @@ transparent trait ScalaStream[@specialized(Float, Double) A]: val end = System.nanoTime() FiniteDuration(end - start, TimeUnit.NANOSECONDS) -> r + inline def runInitArrays(): FiniteDuration = timed(initArrays())._1 + inline def runReadArrays(): FiniteDuration = timed(readArrays())._1 inline def runAll(times: Int)(using Fractional[A]): (Timings[Vector[FiniteDuration]], A) = val copy = ArrayBuffer.fill[FiniteDuration](times)(Duration.Zero) val mul = ArrayBuffer.fill[FiniteDuration](times)(Duration.Zero) @@ -62,7 +65,6 @@ transparent trait ScalaStream[@specialized(Float, Double) A]: def data(): Data[A] - trait Fractional[@specialized(Double, Float) A]: def toFractional(f: Float): A def toFractional(f: Double): A @@ -77,13 +79,13 @@ trait Fractional[@specialized(Double, Float) A]: extension (x: Int) inline def fractional = toFractional(x.toFloat) extension (x: Long) inline def fractional = toFractional(x.toDouble) extension (x: A) - inline def +(y: A) = add(x, y) - inline def -(y: A) = sub(x, y) - inline def *(y: A) = mul(x, y) - inline def /(y: A) = div(x, y) - inline def >(y: A) = compare(x, y) > 0 - inline def <(y: A) = compare(x, y) < 0 - inline def abs_ = abs(x) + inline def +(y: A) = add(x, y) + inline def -(y: A) = sub(x, y) + inline def *(y: A) = mul(x, y) + inline def /(y: A) = div(x, y) + inline def >(y: A) = compare(x, y) > 0 + inline def <(y: A) = compare(x, y) < 0 + inline def abs_ = abs(x) end Fractional given FloatFractional: Fractional[Float] with @@ -204,7 +206,7 @@ object App: validateXs("c", vec.c, goldC) dotSum.foreach { sum => - val goldSum = (goldA * goldB) * (config.options.arraysize).fractional + val goldSum = (goldA * goldB) * config.options.arraysize.fractional val error = ((sum - goldSum) / goldSum).abs_ if error > 1.fractional / 100000000.fractional then Console.err.println( @@ -238,10 +240,10 @@ object App: ) println(s"Running ${config.benchmark match { - case Benchmark.All => "kernels" - case Benchmark.Triad => "triad" - case Benchmark.NStream => "nstream" - }} ${opt.numtimes} times") + case Benchmark.All => "kernels" + case Benchmark.Triad => "triad" + case Benchmark.NStream => "nstream" + }} ${opt.numtimes} times") if config.benchmark == Benchmark.Triad then println(s"Number of elements: ${opt.arraysize}") @@ -288,11 +290,38 @@ object App: println(header.map(_._1.padTo(padding, ' ')).mkString(sep)) println(rows.map(_.map(_._2.padTo(padding, ' ')).mkString(sep)).mkString("\n")) + def showInit(init: FiniteDuration, read: FiniteDuration): Unit = { + val setup = + Vector(("Init", init.seconds, 3 * arrayBytes), ("Read", read.seconds, 3 * arrayBytes)) + if opt.csv then + tabulate( + setup.map((name, elapsed, totalBytes) => + Vector( + "phase" -> name, + "n_elements" -> opt.arraysize.toString, + "sizeof" -> arrayBytes.toString, + s"max_m${if opt.mibibytes then "i" else ""}bytes_per_sec" -> + (megaScale * totalBytes.toDouble / elapsed).toString, + "runtime" -> elapsed.toString + ) + ): _* + ) + else + for (name, elapsed, totalBytes) <- setup do + println( + f"$name: $elapsed%.5f s (=${megaScale * totalBytes.toDouble / elapsed}%.5f M${ + if opt.mibibytes then "i" else "" + }Bytes/sec)" + ) + } + val stream = mkStream(config) - stream.initArrays() + val init = stream.runInitArrays() config.benchmark match case Benchmark.All => val (results, sum) = stream.runAll(opt.numtimes) + val read = stream.runReadArrays() + showInit(init, read) validate(stream.data(), config, Some(sum)) tabulate( mkRow(results.copy, "Copy", 2 * arrayBytes), @@ -303,10 +332,14 @@ object App: ) case Benchmark.NStream => val result = stream.runNStream(opt.numtimes) + val read = stream.runReadArrays() + showInit(init, read) validate(stream.data(), config) tabulate(mkRow(result, "Nstream", 4 * arrayBytes)) case Benchmark.Triad => - val results = stream.runTriad(opt.numtimes) + val results = stream.runTriad(opt.numtimes) + val read = stream.runReadArrays() + showInit(init, read) val totalBytes = 3 * arrayBytes * opt.numtimes val bandwidth = megaScale * (totalBytes / results.seconds) println(f"Runtime (seconds): ${results.seconds}%.5f")