forked from saddle/saddle
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add specialization and loop optis benchmark suites
- Loading branch information
Showing
2 changed files
with
131 additions
and
0 deletions.
There are no files selected for viewing
73 changes: 73 additions & 0 deletions
73
saddle-jmh/src/main/scala/org/saddle/LoopOptimizations.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package org.saddle | ||
|
||
import org.openjdk.jmh.annotations._ | ||
|
||
/** Benchmark suite comparing different loop patterns and the impact of loop optimizations. | ||
* https://wiki.openjdk.java.net/pages/viewpage.action?pageId=20415918 | ||
*/ | ||
@State(Scope.Benchmark) | ||
@Warmup(iterations = 10) | ||
@Measurement(iterations = 10) | ||
@Fork(1) | ||
@Threads(1) | ||
class LoopOptimisations { | ||
@Param(Array("10000")) | ||
var size: Int = _ | ||
var arr: Array[Double] = _ | ||
var vec1: Vec[Double] = _ | ||
var b: Double = _ | ||
|
||
@Setup(Level.Iteration) | ||
def setup() = { | ||
arr = vec.rand(size).toArray | ||
vec1 = Vec(arr) | ||
b = scala.util.Random.nextDouble() | ||
} | ||
|
||
@Benchmark | ||
/** Simplest variant, should trigger vectorization and other optimisations. | ||
*/ | ||
def array(): Array[Double] = { | ||
var i = 0 | ||
while (i < arr.length) { | ||
arr(i) = arr(i) + b | ||
i += 1 | ||
} | ||
arr | ||
} | ||
|
||
/** hand-unrolled loops prevent vectorization and potentially other | ||
* optimisations | ||
*/ | ||
@Benchmark | ||
def arrayHandUnrolled(): Array[Double] = { | ||
var i = 0 | ||
val length = arr.length | ||
val unrolledStride = 2 | ||
val preloopIterations = length % unrolledStride | ||
while (i < preloopIterations) { | ||
arr(i) += b | ||
i += 1 | ||
} | ||
while (i < length) { | ||
arr(i + 0) += b | ||
arr(i + 1) += b | ||
i += unrolledStride | ||
} | ||
arr | ||
} | ||
|
||
@Benchmark | ||
def vecBinOps(): Vec[Double] = { | ||
import ops.BinOps._ | ||
vec1 += b | ||
vec1 | ||
} | ||
|
||
@Benchmark | ||
def vecBinOpsMacros(): Vec[Double] = { | ||
import macros.BinOps._ | ||
vec1 += b | ||
vec1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package org.saddle | ||
|
||
import org.saddle.scalar.ScalarTag | ||
import org.saddle.vec.VecDefault | ||
|
||
import org.openjdk.jmh.annotations._ | ||
|
||
class VecBoxed[T: ScalarTag](values: Array[T]) | ||
extends VecDefault[T](values, implicitly[ScalarTag[T]]) | ||
|
||
/** Benchmark suite illustrating the performance boost of specialization. | ||
*/ | ||
@State(Scope.Benchmark) | ||
@Warmup(iterations = 3) | ||
@Measurement(iterations = 1) | ||
@Fork(1) | ||
@Threads(1) | ||
class Specialization { | ||
@Param(Array("10", "10000")) | ||
var size: Int = _ | ||
|
||
var v1: Vec[Double] = _ | ||
var v2: VecBoxed[Double] = _ | ||
var b: Double = _ | ||
|
||
@Setup(Level.Iteration) | ||
def setup() = { | ||
v1 = vec.rand(size) | ||
v2 = new VecBoxed(v1.toArray) | ||
b = scala.util.Random.nextDouble() | ||
} | ||
@Benchmark | ||
def vecBoxed(): Vec[Double] = { | ||
import org.saddle.ops.BinOps._ | ||
v2 /= b | ||
v2 | ||
} | ||
|
||
@Benchmark | ||
def vecSpecialized(): Vec[Double] = { | ||
import org.saddle.ops.BinOps._ | ||
v1 += b | ||
v1 | ||
} | ||
|
||
@Benchmark | ||
def array(): Vec[Double] = { | ||
val v1a = v1.toArray | ||
var i = 0 | ||
i = 0 | ||
val N = v1a.length | ||
while (i < N) { | ||
v1a(i) += b | ||
i += 1 | ||
} | ||
v1 | ||
} | ||
} |