Revise benchmarks code

Revise benchmarks code by using kotlinx.benchmark type aliases
(it will simplify creating multiplatform benchmarks), using
Blackhole class to consume results, moving all the constant state
to private companion objects
This commit is contained in:
Iaroslav Postovalov 2021-03-10 21:35:28 +07:00
parent fe9334d570
commit 940718098d
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
8 changed files with 134 additions and 106 deletions

View File

@ -1,34 +1,38 @@
package space.kscience.kmath.benchmarks package space.kscience.kmath.benchmarks
import org.openjdk.jmh.annotations.Benchmark import kotlinx.benchmark.Benchmark
import org.openjdk.jmh.annotations.Scope import kotlinx.benchmark.Blackhole
import org.openjdk.jmh.annotations.State import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import java.nio.IntBuffer import java.nio.IntBuffer
@State(Scope.Benchmark) @State(Scope.Benchmark)
internal class ArrayBenchmark { internal class ArrayBenchmark {
@Benchmark @Benchmark
fun benchmarkArrayRead() { fun benchmarkArrayRead(blackhole: Blackhole) {
var res = 0 var res = 0
for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.array[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i] for (i in 1..size) res += array[size - i]
blackhole.consume(res)
} }
@Benchmark @Benchmark
fun benchmarkBufferRead() { fun benchmarkBufferRead(blackhole: Blackhole) {
var res = 0 var res = 0
for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.arrayBuffer[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i] for (i in 1..size) res += arrayBuffer[size - i]
blackhole.consume(res)
} }
@Benchmark @Benchmark
fun nativeBufferRead() { fun nativeBufferRead(blackhole: Blackhole) {
var res = 0 var res = 0
for (i in 1..space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) res += space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.nativeBuffer[space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size - i] for (i in 1..size) res += nativeBuffer[size - i]
blackhole.consume(res)
} }
companion object { private companion object {
const val size: Int = 1000 private const val size = 1000
val array: IntArray = IntArray(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) { it } private val array = IntArray(size) { it }
val arrayBuffer: IntBuffer = IntBuffer.wrap(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.array) private val arrayBuffer = IntBuffer.wrap(array)
val nativeBuffer: IntBuffer = IntBuffer.allocate(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size).also { for (i in 0 until space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) it.put(i, i) } private val nativeBuffer = IntBuffer.allocate(size).also { for (i in 0 until size) it.put(i, i) }
} }
} }

View File

@ -1,8 +1,8 @@
package space.kscience.kmath.benchmarks package space.kscience.kmath.benchmarks
import org.openjdk.jmh.annotations.Benchmark import kotlinx.benchmark.Benchmark
import org.openjdk.jmh.annotations.Scope import kotlinx.benchmark.Scope
import org.openjdk.jmh.annotations.State import kotlinx.benchmark.State
import space.kscience.kmath.complex.Complex import space.kscience.kmath.complex.Complex
import space.kscience.kmath.complex.complex import space.kscience.kmath.complex.complex
import space.kscience.kmath.structures.MutableBuffer import space.kscience.kmath.structures.MutableBuffer
@ -28,7 +28,7 @@ internal class BufferBenchmark {
} }
} }
companion object { private companion object {
const val size: Int = 100 private const val size = 100
} }
} }

View File

@ -1,8 +1,9 @@
package space.kscience.kmath.benchmarks package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark import kotlinx.benchmark.Benchmark
import org.openjdk.jmh.annotations.Scope import kotlinx.benchmark.Blackhole
import org.openjdk.jmh.annotations.State import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.commons.linear.CMMatrixContext import space.kscience.kmath.commons.linear.CMMatrixContext
import space.kscience.kmath.ejml.EjmlMatrixContext import space.kscience.kmath.ejml.EjmlMatrixContext
import space.kscience.kmath.linear.BufferMatrixContext import space.kscience.kmath.linear.BufferMatrixContext
@ -17,7 +18,7 @@ import kotlin.random.Random
internal class DotBenchmark { internal class DotBenchmark {
companion object { companion object {
val random = Random(12224) val random = Random(12224)
val dim = 1000 const val dim = 1000
//creating invertible matrix //creating invertible matrix
val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
@ -31,37 +32,37 @@ internal class DotBenchmark {
} }
@Benchmark @Benchmark
fun cmDot() { fun cmDot(blackhole: Blackhole) {
CMMatrixContext { CMMatrixContext {
cmMatrix1 dot cmMatrix2 blackhole.consume(cmMatrix1 dot cmMatrix2)
} }
} }
@Benchmark @Benchmark
fun ejmlDot() { fun ejmlDot(blackhole: Blackhole) {
EjmlMatrixContext { EjmlMatrixContext {
ejmlMatrix1 dot ejmlMatrix2 blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
} }
} }
@Benchmark @Benchmark
fun ejmlDotWithConversion() { fun ejmlDotWithConversion(blackhole: Blackhole) {
EjmlMatrixContext { EjmlMatrixContext {
matrix1 dot matrix2 blackhole.consume(matrix1 dot matrix2)
} }
} }
@Benchmark @Benchmark
fun bufferedDot() { fun bufferedDot(blackhole: Blackhole) {
BufferMatrixContext(RealField, Buffer.Companion::real).invoke { BufferMatrixContext(RealField, Buffer.Companion::real).invoke {
matrix1 dot matrix2 blackhole.consume(matrix1 dot matrix2)
} }
} }
@Benchmark @Benchmark
fun realDot() { fun realDot(blackhole: Blackhole) {
RealMatrixContext { RealMatrixContext {
matrix1 dot matrix2 blackhole.consume(matrix1 dot matrix2)
} }
} }
} }

View File

@ -1,64 +1,62 @@
package space.kscience.kmath.benchmarks package space.kscience.kmath.benchmarks
import org.openjdk.jmh.annotations.Benchmark import kotlinx.benchmark.Benchmark
import org.openjdk.jmh.annotations.Scope import kotlinx.benchmark.Blackhole
import org.openjdk.jmh.annotations.State import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.asm.compile import space.kscience.kmath.asm.compile
import space.kscience.kmath.ast.mstInField import space.kscience.kmath.ast.mstInField
import space.kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.expressionInField import space.kscience.kmath.expressions.expressionInField
import space.kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.expressions.symbol import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.RealField
import space.kscience.kmath.operations.bindSymbol import space.kscience.kmath.operations.bindSymbol
import kotlin.random.Random import kotlin.random.Random
@State(Scope.Benchmark) @State(Scope.Benchmark)
internal class ExpressionsInterpretersBenchmark { internal class ExpressionsInterpretersBenchmark {
private val algebra: Field<Double> = RealField
val x by symbol
@Benchmark @Benchmark
fun functionalExpression() { fun functionalExpression(blackhole: Blackhole) {
val expr = algebra.expressionInField { val expr = algebra.expressionInField {
val x = bindSymbol(x) val x = bindSymbol(x)
x * const(2.0) + const(2.0) / x - const(16.0) x * const(2.0) + const(2.0) / x - const(16.0)
} }
invokeAndSum(expr) invokeAndSum(expr, blackhole)
} }
@Benchmark @Benchmark
fun mstExpression() { fun mstExpression(blackhole: Blackhole) {
val expr = algebra.mstInField { val expr = algebra.mstInField {
val x = bindSymbol(x) val x = bindSymbol(x)
x * 2.0 + 2.0 / x - 16.0 x * 2.0 + 2.0 / x - 16.0
} }
invokeAndSum(expr) invokeAndSum(expr, blackhole)
} }
@Benchmark @Benchmark
fun asmExpression() { fun asmExpression(blackhole: Blackhole) {
val expr = algebra.mstInField { val expr = algebra.mstInField {
val x = bindSymbol(x) val x = bindSymbol(x)
x * 2.0 + 2.0 / x - 16.0 x * 2.0 + 2.0 / x - 16.0
}.compile() }.compile()
invokeAndSum(expr) invokeAndSum(expr, blackhole)
} }
@Benchmark @Benchmark
fun rawExpression() { fun rawExpression(blackhole: Blackhole) {
val expr = Expression<Double> { args -> val expr = Expression<Double> { args ->
val x = args.getValue(x) val x = args.getValue(x)
x * 2.0 + 2.0 / x - 16.0 x * 2.0 + 2.0 / x - 16.0
} }
invokeAndSum(expr)
invokeAndSum(expr, blackhole)
} }
private fun invokeAndSum(expr: Expression<Double>) { private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
val random = Random(0) val random = Random(0)
var sum = 0.0 var sum = 0.0
@ -66,6 +64,11 @@ internal class ExpressionsInterpretersBenchmark {
sum += expr(x to random.nextDouble()) sum += expr(x to random.nextDouble())
} }
println(sum) blackhole.consume(sum)
}
private companion object {
private val algebra = RealField
private val x by symbol
} }
} }

View File

@ -1,8 +1,9 @@
package space.kscience.kmath.benchmarks package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark import kotlinx.benchmark.Benchmark
import org.openjdk.jmh.annotations.Scope import kotlinx.benchmark.Blackhole
import org.openjdk.jmh.annotations.State import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.commons.linear.CMMatrixContext import space.kscience.kmath.commons.linear.CMMatrixContext
import space.kscience.kmath.commons.linear.CMMatrixContext.dot import space.kscience.kmath.commons.linear.CMMatrixContext.dot
import space.kscience.kmath.commons.linear.inverse import space.kscience.kmath.commons.linear.inverse
@ -18,7 +19,7 @@ import kotlin.random.Random
internal class LinearAlgebraBenchmark { internal class LinearAlgebraBenchmark {
companion object { companion object {
val random = Random(1224) val random = Random(1224)
val dim = 100 const val dim = 100
//creating invertible matrix //creating invertible matrix
val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 } val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
@ -27,21 +28,21 @@ internal class LinearAlgebraBenchmark {
} }
@Benchmark @Benchmark
fun kmathLupInversion() { fun kmathLupInversion(blackhole: Blackhole) {
MatrixContext.real.inverseWithLup(matrix) blackhole.consume(MatrixContext.real.inverseWithLup(matrix))
} }
@Benchmark @Benchmark
fun cmLUPInversion() { fun cmLUPInversion(blackhole: Blackhole) {
with(CMMatrixContext) { with(CMMatrixContext) {
inverse(matrix) blackhole.consume(inverse(matrix))
} }
} }
@Benchmark @Benchmark
fun ejmlInverse() { fun ejmlInverse(blackhole: Blackhole) {
with(EjmlMatrixContext) { with(EjmlMatrixContext) {
inverse(matrix) blackhole.consume(inverse(matrix))
} }
} }
} }

View File

@ -1,8 +1,9 @@
package space.kscience.kmath.benchmarks package space.kscience.kmath.benchmarks
import org.openjdk.jmh.annotations.Benchmark import kotlinx.benchmark.Benchmark
import org.openjdk.jmh.annotations.Scope import kotlinx.benchmark.Blackhole
import org.openjdk.jmh.annotations.State import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.RealField
import space.kscience.kmath.structures.Buffer import space.kscience.kmath.structures.Buffer
@ -10,35 +11,38 @@ import space.kscience.kmath.structures.Buffer
@State(Scope.Benchmark) @State(Scope.Benchmark)
internal class NDFieldBenchmark { internal class NDFieldBenchmark {
@Benchmark @Benchmark
fun autoFieldAdd() { fun autoFieldAdd(blackhole: Blackhole) {
with(autoField) { with(autoField) {
var res: NDStructure<Double> = one var res: NDStructure<Double> = one
repeat(n) { res += one } repeat(n) { res += one }
blackhole.consume(res)
} }
} }
@Benchmark @Benchmark
fun specializedFieldAdd() { fun specializedFieldAdd(blackhole: Blackhole) {
with(specializedField) { with(specializedField) {
var res: NDStructure<Double> = one var res: NDStructure<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
blackhole.consume(res)
} }
} }
@Benchmark @Benchmark
fun boxingFieldAdd() { fun boxingFieldAdd(blackhole: Blackhole) {
with(genericField) { with(genericField) {
var res: NDStructure<Double> = one var res: NDStructure<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
blackhole.consume(res)
} }
} }
companion object { private companion object {
const val dim: Int = 1000 private const val dim = 1000
const val n: Int = 100 private const val n = 100
val autoField = NDAlgebra.auto(RealField, dim, dim) private val autoField = NDAlgebra.auto(RealField, dim, dim)
val specializedField: RealNDField = NDAlgebra.real(dim, dim) private val specializedField = NDAlgebra.real(dim, dim)
val genericField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim) private val genericField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim)
} }
} }

View File

@ -1,51 +1,61 @@
package space.kscience.kmath.benchmarks package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import org.jetbrains.bio.viktor.F64Array import org.jetbrains.bio.viktor.F64Array
import org.openjdk.jmh.annotations.Benchmark import space.kscience.kmath.nd.NDAlgebra
import org.openjdk.jmh.annotations.Scope import space.kscience.kmath.nd.NDStructure
import org.openjdk.jmh.annotations.State import space.kscience.kmath.nd.auto
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.real
import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.RealField
import space.kscience.kmath.viktor.ViktorNDField import space.kscience.kmath.viktor.ViktorNDField
@State(Scope.Benchmark) @State(Scope.Benchmark)
internal class ViktorBenchmark { internal class ViktorBenchmark {
final val dim: Int = 1000
final val n: Int = 100
// automatically build context most suited for given type.
final val autoField: NDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
final val realField: RealNDField = NDAlgebra.real(dim, dim)
final val viktorField: ViktorNDField = ViktorNDField(dim, dim)
@Benchmark @Benchmark
fun automaticFieldAddition() { fun automaticFieldAddition(blackhole: Blackhole) {
with(autoField) { with(autoField) {
var res: NDStructure<Double> = one var res: NDStructure<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
blackhole.consume(res)
} }
} }
@Benchmark @Benchmark
fun realFieldAddition() { fun realFieldAddition(blackhole: Blackhole) {
with(realField) { with(realField) {
var res: NDStructure<Double> = one var res: NDStructure<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
blackhole.consume(res)
} }
} }
@Benchmark @Benchmark
fun viktorFieldAddition() { fun viktorFieldAddition(blackhole: Blackhole) {
with(viktorField) { with(viktorField) {
var res = one var res = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
blackhole.consume(res)
} }
} }
@Benchmark @Benchmark
fun rawViktor() { fun rawViktor(blackhole: Blackhole) {
val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim)) val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim))
var res = one var res = one
repeat(n) { res = res + one } repeat(n) { res = res + one }
blackhole.consume(res)
}
private companion object {
private const val dim = 1000
private const val n = 100
// automatically build context most suited for given type.
private val autoField = NDAlgebra.auto(RealField, dim, dim)
private val realField = NDAlgebra.real(dim, dim)
private val viktorField = ViktorNDField(dim, dim)
} }
} }

View File

@ -1,48 +1,53 @@
package space.kscience.kmath.benchmarks package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import org.jetbrains.bio.viktor.F64Array import org.jetbrains.bio.viktor.F64Array
import org.openjdk.jmh.annotations.Benchmark import space.kscience.kmath.nd.NDAlgebra
import org.openjdk.jmh.annotations.Scope import space.kscience.kmath.nd.auto
import org.openjdk.jmh.annotations.State import space.kscience.kmath.nd.real
import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.RealField import space.kscience.kmath.operations.RealField
import space.kscience.kmath.viktor.ViktorNDField import space.kscience.kmath.viktor.ViktorNDField
@State(Scope.Benchmark) @State(Scope.Benchmark)
internal class ViktorLogBenchmark { internal class ViktorLogBenchmark {
final val dim: Int = 1000
final val n: Int = 100
// automatically build context most suited for given type.
final val autoField: NDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
final val realField: RealNDField = NDAlgebra.real(dim, dim)
final val viktorField: ViktorNDField = ViktorNDField(intArrayOf(dim, dim))
@Benchmark @Benchmark
fun realFieldLog() { fun realFieldLog(blackhole: Blackhole) {
with(realField) { with(realField) {
val fortyTwo = produce { 42.0 } val fortyTwo = produce { 42.0 }
var res = one var res = one
repeat(n) { res = ln(fortyTwo) } repeat(n) { res = ln(fortyTwo) }
blackhole.consume(res)
} }
} }
@Benchmark @Benchmark
fun viktorFieldLog() { fun viktorFieldLog(blackhole: Blackhole) {
with(viktorField) { with(viktorField) {
val fortyTwo = produce { 42.0 } val fortyTwo = produce { 42.0 }
var res = one var res = one
repeat(n) { res = ln(fortyTwo) } repeat(n) { res = ln(fortyTwo) }
blackhole.consume(res)
} }
} }
@Benchmark @Benchmark
fun rawViktorLog() { fun rawViktorLog(blackhole: Blackhole) {
val fortyTwo = F64Array.full(dim, dim, init = 42.0) val fortyTwo = F64Array.full(dim, dim, init = 42.0)
var res: F64Array lateinit var res: F64Array
repeat(n) { repeat(n) { res = fortyTwo.log() }
res = fortyTwo.log() blackhole.consume(res)
} }
private companion object {
private const val dim = 1000
private const val n = 100
// automatically build context most suited for given type.
private val autoField = NDAlgebra.auto(RealField, dim, dim)
private val realField = NDAlgebra.real(dim, dim)
private val viktorField = ViktorNDField(intArrayOf(dim, dim))
} }
} }