diff --git a/build.sc b/build.sc index 5302340..8bf4278 100644 --- a/build.sc +++ b/build.sc @@ -1,6 +1,6 @@ import $ivy.`com.github.lolgab::mill-crossplatform::0.2.4` -import $ivy.`io.github.quafadas::millSite::0.0.31-DIRTY1d54e88b` +import $ivy.`io.github.quafadas::millSite::0.0.32` import $ivy.`de.tototec::de.tobiasroeser.mill.vcs.version::0.4.0` import $ivy.`com.lihaoyi::mill-contrib-jmh:` diff --git a/site/docs/_assets/plots/countTrue.vg.json b/site/docs/_assets/plots/countTrue.vg.json new file mode 100644 index 0000000..bb480c9 --- /dev/null +++ b/site/docs/_assets/plots/countTrue.vg.json @@ -0,0 +1,141 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "data": { + "url": "../../benchmarks/benchmark_history.json", + "format": { + "type": "json" + } + }, + "transform": [ + { + "calculate": "replace(datum.benchmark, 'vecxt.benchmark.', '')", + "as": "benchmark" + }, + { + "calculate": "datetime(substring(datum.date,0, 4)+ '-' + substring(datum.date,4, 6) + '-' + substring(datum.date,6, 8))", + "as": "date" + }, + { + "joinaggregate": [ + { + "op": "max", + "field": "date", + "as": "maxDate" + } + ] + }, + { + "filter": { + "field": "benchmark", + "oneOf": [ + "CountTrueBenchmark.countTrue_loop", + "CountTrueBenchmark.countTrue_loop_vec" + ] + } + }, + { + "window": [{ "op": "dense_rank", "as": "rank" }], + "sort": [{ "field": "date", "order": "descending" }] + }, + { "filter": "datum.rank <= 1" } + ], + "vconcat": [ + { + "layer": [ + { + "mark": "errorbar", + "encoding": { + "x": { + "field": "scoreLowerConfidence", + "type": "quantitative", + "scale": { "zero": false }, + "title": "ops / s" + }, + "x2": { "field": "scoreUpperConfidence" }, + "y": { "field": "benchmark", "type": "ordinal" } + } + }, + { + "mark": { + "type": "point", + "filled": true, + "color": "black" + }, + "encoding": { + "x": { + "field": "score", + "type": "quantitative" + }, + "y": { "field": "benchmark", "type": "ordinal" } + } + } + ], + "transform": [{ "filter": "(datum.params.len == '3')" }] + }, + { + "layer": [ + { + "mark": "errorbar", + "encoding": { + "x": { + "field": "scoreLowerConfidence", + "type": "quantitative", + "scale": { "zero": false }, + "title": "ops / s" + }, + "x2": { "field": "scoreUpperConfidence" }, + "y": { "field": "benchmark", "type": "ordinal" } + } + }, + { + "mark": { + "type": "point", + "filled": true, + "color": "black" + }, + "encoding": { + "x": { + "field": "score", + "type": "quantitative" + }, + "y": { "field": "benchmark", "type": "ordinal" } + } + } + ], + "transform": [{ "filter": "(datum.params.len == '128')" }] + }, + + { + "layer": [ + { + "mark": "errorbar", + "encoding": { + "x": { + "field": "scoreLowerConfidence", + "type": "quantitative", + "scale": { "zero": false }, + "title": "ops / s" + }, + "x2": { "field": "scoreUpperConfidence" }, + "y": { "field": "benchmark", "type": "ordinal" } + } + }, + { + "mark": { + "type": "point", + "filled": true, + "color": "black" + }, + "encoding": { + "x": { + "field": "score", + "type": "quantitative" + }, + "y": { "field": "benchmark", "type": "ordinal" } + } + } + ], + "transform": [{ "filter": "(datum.params.len == '100000')" }] + } + ] +} diff --git a/site/docs/_assets/plots/sum_over_time.vg.json b/site/docs/_assets/plots/sum_over_time.vg.json new file mode 100644 index 0000000..a8af31f --- /dev/null +++ b/site/docs/_assets/plots/sum_over_time.vg.json @@ -0,0 +1,133 @@ +{ + "$schema": "https://vega.github.io/schema/vega-lite/v5.json", + "data": { + "url": "../../benchmarks/benchmark_history.json", + "format": { + "type": "json" + } + }, + "transform": [ + { + "calculate": "replace(datum.benchmark, 'vecxt.benchmark.', '')", + "as": "benchmark" + }, + { + "calculate": "datetime(substring(datum.date,0, 4)+ '-' + substring(datum.date,4, 6) + '-' + substring(datum.date,6, 8))", + "as": "date" + }, + { + "filter": { + "field": "benchmark", + "oneOf": ["AddScalarBenchmark.vecxt_add_vec"] + } + }, + { + "window": [{ "op": "dense_rank", "as": "rank" }], + "sort": [{ "field": "date", "order": "descending" }] + } + ], + "vconcat": [ + { + "layer": [ + { + "title": "n = 10", + "mark": { + "type": "line", + "color": "black" + }, + "encoding": { + "y": { + "field": "score", + "type": "quantitative", + "scale": { "zero": false }, + "title": "ops/s" + }, + "x": { "field": "date", "timeUnit": "date" } + } + }, + { + "mark": { "opacity": 0.3, "type": "area", "color": "#85C5A6" }, + "encoding": { + "x": { "field": "date", "timeUnit": "date" }, + "y": { + "field": "scoreUpperConfidence", + "type": "quantitative" + }, + "y2": { + "field": "scoreLowerConfidence" + } + } + } + ], + "transform": [{ "filter": "(datum.params.n == '10')" }] + }, + { + "layer": [ + { + "title": "n = 1000", + "mark": { + "type": "line", + "color": "black" + }, + "encoding": { + "y": { + "field": "score", + "type": "quantitative", + "scale": { "zero": false } + }, + "x": { "field": "date", "timeUnit": "date" } + } + }, + { + "mark": { "opacity": 0.3, "type": "area", "color": "#85C5A6" }, + "encoding": { + "x": { "field": "date", "timeUnit": "date" }, + "y": { + "field": "scoreUpperConfidence", + "type": "quantitative", + "title": "ops/s" + }, + "y2": { + "field": "scoreLowerConfidence" + } + } + } + ], + "transform": [{ "filter": "(datum.params.n == '1000')" }] + }, + { + "layer": [ + { + "title": "n = 1000000", + "mark": { + "type": "line", + "color": "black" + }, + "encoding": { + "y": { + "field": "score", + "type": "quantitative", + "scale": { "zero": false }, + "title": "ops/s" + }, + "x": { "field": "date", "timeUnit": "date" } + } + }, + { + "mark": { "opacity": 0.3, "type": "area", "color": "#85C5A6" }, + "encoding": { + "x": { "field": "date", "timeUnit": "date" }, + "y": { + "field": "scoreUpperConfidence", + "type": "quantitative" + }, + "y2": { + "field": "scoreLowerConfidence" + } + } + } + ], + "transform": [{ "filter": "(datum.params.n == '100000')" }] + } + ] +} diff --git a/site/docs/_docs/benchmarks/countTrue.md b/site/docs/_docs/benchmarks/countTrue.md new file mode 100644 index 0000000..b90a41d --- /dev/null +++ b/site/docs/_docs/benchmarks/countTrue.md @@ -0,0 +1,16 @@ + +You may need to refresh the page. +https://github.com/scala/scala3/issues/21637 + +Here is the comparison of the standard `while` loop with the vectorised version. +
+ + + +# Conclusion diff --git a/site/docs/_docs/benchmarks/sum.md b/site/docs/_docs/benchmarks/sum.md index 71e2c4e..9c9baab 100644 --- a/site/docs/_docs/benchmarks/sum.md +++ b/site/docs/_docs/benchmarks/sum.md @@ -6,13 +6,22 @@ Here is the comparison of the standard `while` loop with the vectorised version.
+And the function left in vexct over time (against regressions) + +
+ + + + The two implementations are; ```scala sc:nocompile diff --git a/vecxt/src/package.scala b/vecxt/src/package.scala index 0f13c72..6df461a 100644 --- a/vecxt/src/package.scala +++ b/vecxt/src/package.scala @@ -134,6 +134,17 @@ object Matrix: extension [A](d: Array[A]) def print: String = d.mkString("[", ",", "],") extension (m: Matrix) + + /** element retrieval + */ + inline def apply(b: Tuple2[Int, Int])(using inline boundsCheck: BoundsCheck) = + indexCheckMat(m, b) + val idx = b._1 * m._2._2 + b._2 + m._1(idx) + end apply + + /** element update + */ inline def update(loc: Tuple2[Int, Int], value: Double)(using inline boundsCheck: BoundsCheck) = indexCheckMat(m, loc) val idx = loc._1 * m._2._2 + loc._2 @@ -155,12 +166,12 @@ object Matrix: var i = 0 while i < newCols.length do - val oldCol = newCols(i) - val stride = oldCol * m.cols + val colpos = newCols(i) + val stride = colpos * m.cols var j = 0 while j < newRows.length do - val oldRow = newRows(j) - newArr(idx) = m._1(stride + oldRow) + val rowPos = newRows(j) + newArr(idx) = m._1(stride + rowPos) idx += 1 j += 1 end while @@ -173,24 +184,6 @@ object Matrix: inline def raw: NArray[Double] = m._1 - /** Zelement retrieval - */ - inline def apply(b: Tuple2[Int, Int]) = - val indexes = b.toList.asInstanceOf[List[Int]] - val dimensions = m._2.toList.asInstanceOf[List[Int]] - - assert(indexes.length == dimensions.length) - - val linearIndex = indexes - .zip(dimensions.scanRight(1)(_ * _).tail) - .map { case (index, stride) => - index * stride - } - .sum - - m._1(linearIndex) - end apply - inline def @@(b: Matrix)(using inline boundsCheck: BoundsCheck): Matrix = m.matmul(b) inline def *=(d: Double): Unit = m._1.multInPlace(d) @@ -211,11 +204,9 @@ object Matrix: val result = new NArray[Double](m.cols) val cols = m.cols var j = 0 - var k = 0 while j < m.cols do - result(k) = m._1(i + j * m.rows) + result(j) = m._1(i + j * m.rows) j += 1 - k += 1 end while result end row @@ -229,11 +220,9 @@ object Matrix: val result = new NArray[Double](m.rows) val cols = m.cols var j = 0 - var k = 0 while j < m.rows do - result(k) = m._1(i * m.cols + j) + result(j) = m._1(i * m.cols + j) j += 1 - k += 1 end while result end col diff --git a/vecxt/test/src/arrayExtensions.test.scala b/vecxt/test/src/arrayExtensions.test.scala index c02116e..66ecd02 100644 --- a/vecxt/test/src/arrayExtensions.test.scala +++ b/vecxt/test/src/arrayExtensions.test.scala @@ -54,7 +54,7 @@ class ArrayExtensionSuite extends munit.FunSuite: } - test("check vector operator precendance".only) { + test("check vector operator precendance") { val v1 = NArray[Double](1.0, 2.0, 3.0) val v2 = NArray[Double](3.0, 2.0, 1.0) diff --git a/vecxt/test/src/matrixExt.test.scala b/vecxt/test/src/matrixExt.test.scala index fba8048..9a044a5 100644 --- a/vecxt/test/src/matrixExt.test.scala +++ b/vecxt/test/src/matrixExt.test.scala @@ -8,12 +8,12 @@ import vecxt.BoundsCheck.DoBoundsCheck.yes class TensorExtensionSuite extends FunSuite: - test("operator precedance".only) { + test("operator precedance") { val mat1 = Matrix.eye(2) val mat2 = Matrix(mat1.raw * 2, (mat1.rows, mat1.cols)) val mat3 = mat1 + mat1 @@ mat2 - assertEqualsDouble(mat3(0, 0), 3.0, 0.00001) + assertEqualsDouble(mat3((0, 0)), 3.0, 0.00001) }