Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
Quafadas committed Nov 11, 2024
1 parent 9b4920a commit 8b21025
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 39 deletions.
9 changes: 9 additions & 0 deletions site/docs/_blog/_posts/2024-11-11-SIMD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: SIMD on the JVM
---

One of the reason for starting this project, was an excuse to have a hard look at the SIMD promise of project panama on the JVM. Here are the key takeaways.

- Anything involving integer division is catastrophically slow. There is no hardware instruction for integer division, and so it falls back to a slow implementation
- Benchmarking is soverign. Just using SIMD can yield no benefit, some benefit, or make you algorithm 50x slower. Benchmark benchmark benchmark.
-
13 changes: 13 additions & 0 deletions todo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Important todos at 2024-11-11

- [ ] solidify benchmarking
- [ ] reusable plot elements
- [ ] via named tuples and upickle?
- [ ] Beautiful display in scala JS through MathMl
- [ ] PR to scala JS dom in progress
- [ ] PR to scalal DOM types
- [ ] PR to laminar
- [ ] Investiagte the feasibility of WASM?
- [ ] Make matrix high dimensional
- [ ] Test with spire
- [ ] xPlatform LAPACK facade
47 changes: 23 additions & 24 deletions vecxt/jvm/src/arrays.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ import vecxt.BoundsCheck.BoundsCheck

object arrays:

final val spd = DoubleVector.SPECIES_PREFERRED
final val spb = ByteVector.SPECIES_PREFERRED

extension (vec: Array[Boolean])
inline def countTrue: Int =
val species = ByteVector.SPECIES_PREFERRED
val l = species.length()
val l = spb.length()
var sum = 0
var i = 0
while i < species.loopBound(vec.length) do
sum = sum + ByteVector.fromBooleanArray(species, vec, i).reduceLanes(VectorOperators.ADD)
while i < spb.loopBound(vec.length) do
sum = sum + ByteVector.fromBooleanArray(spb, vec, i).reduceLanes(VectorOperators.ADD)
i += l
end while

Expand All @@ -48,15 +50,14 @@ object arrays:
end countTrue

inline def &&(thatIdx: Array[Boolean]): Array[Boolean] =
val species = ByteVector.SPECIES_PREFERRED
val l = species.length()
val l = spb.length()
val result: Array[Boolean] = new Array[Boolean](vec.length)
var i = 0

while i < species.loopBound(vec.length) do
while i < spb.loopBound(vec.length) do
ByteVector
.fromBooleanArray(species, vec, i)
.and(ByteVector.fromBooleanArray(species, thatIdx, i))
.fromBooleanArray(spb, vec, i)
.and(ByteVector.fromBooleanArray(spb, thatIdx, i))
.intoBooleanArray(result, i)
i += l
end while
Expand Down Expand Up @@ -152,13 +153,12 @@ object arrays:

inline def increments: Array[Double] =
val out = new Array[Double](vec.length)
val sp = DoubleVector.SPECIES_PREFERRED
val l = sp.length()
val l = spd.length()

var i = 1
while i < sp.loopBound(vec.length - 2) do
val v1 = DoubleVector.fromArray(sp, vec, i)
val v2 = DoubleVector.fromArray(sp, vec, i + 1)
while i < spd.loopBound(vec.length - 2) do
val v1 = DoubleVector.fromArray(spd, vec, i)
val v2 = DoubleVector.fromArray(spd, vec, i + 1)
v2.sub(v1).intoArray(out, i)
i += l
end while
Expand Down Expand Up @@ -242,13 +242,13 @@ object arrays:
// https://www.cuemath.com/sample-variance-formula/
val μ = vec.mean
// vec.map(i => (i - μ) * (i - μ)).sum / (vec.length - 1)
val sp = DoubleVector.SPECIES_PREFERRED
val l = sp.length()
var tmp = DoubleVector.zero(sp)

val l = spd.length()
var tmp = DoubleVector.zero(spd)

var i = 0
while i < sp.loopBound(vec.length) do
val v = DoubleVector.fromArray(sp, vec, i)
while i < spd.loopBound(vec.length) do
val v = DoubleVector.fromArray(spd, vec, i)
val diff = v.sub(μ)
tmp = tmp.add(diff.mul(diff))
i += l
Expand Down Expand Up @@ -276,13 +276,12 @@ object arrays:

inline def sum: Double =
var i: Int = 0
val sp = DoubleVector.SPECIES_PREFERRED
var acc = DoubleVector.zero(sp)
var acc = DoubleVector.zero(spd)

val l = sp.length()
val l = spd.length()

while i < sp.loopBound(vec.length) do
acc = acc.add(DoubleVector.fromArray(sp, vec, i))
while i < spd.loopBound(vec.length) do
acc = acc.add(DoubleVector.fromArray(spd, vec, i))
i += l
end while
var temp = acc.reduceLanes(VectorOperators.ADD)
Expand Down
17 changes: 2 additions & 15 deletions vecxt/jvm/src/matrix.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,16 @@ import vecxt.BoundsCheck.BoundsCheck

object matrix:

// opaque type Tensor = (NArray[Double], Tuple)
// object Tensor:
// def apply[T <: Tuple](a: NArray[Double], b: T)(using ev: TupleOfInts[T] =:= true): Tensor = (a, b)
// end Tensor

// opaque type Vector = (NArray[Double], Tuple1[Int])
// type Vector = Vector1 & Tensor

// object Vector:
// def apply(a: NArray[Double]): Vector = (a, Tuple1(a.size))
// end Vector

/** This is a matrix
*
* ._1 is the matrix values, stored as a single contiguous array ._2 is the dimensions ._2._1 is the number of rows
* ._2._2 is the number of columns
* ._2._2 is the number of columns. You can access the raw array with the .raw method which inlines to the tuple
* call.
*/
opaque type Matrix = (NArray[Double], Tuple2[Int, Int])

object Matrix:

inline def doubleSpecies = DoubleVector.SPECIES_PREFERRED

inline def apply[T <: Tuple2[Int, Int]](raw: NArray[Double], dim: T)(using
inline boundsCheck: BoundsCheck
): Matrix =
Expand Down
2 changes: 2 additions & 0 deletions vecxt/src/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export vecxt.arrays.*
export vecxt.cosineSimilarity
export vecxt.matrixUtil.*
export vecxt.arrayUtil.*

type Col_Row = Tuple2[Int, Int]

0 comments on commit 8b21025

Please sign in to comment.