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
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import java.nio.IntBuffer
@State(Scope.Benchmark)
internal class ArrayBenchmark {
@Benchmark
fun benchmarkArrayRead() {
fun benchmarkArrayRead(blackhole: Blackhole) {
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
fun benchmarkBufferRead() {
fun benchmarkBufferRead(blackhole: Blackhole) {
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
fun nativeBufferRead() {
fun nativeBufferRead(blackhole: Blackhole) {
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 {
const val size: Int = 1000
val array: IntArray = IntArray(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.size) { it }
val arrayBuffer: IntBuffer = IntBuffer.wrap(space.kscience.kmath.benchmarks.ArrayBenchmark.Companion.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 companion object {
private const val size = 1000
private val array = IntArray(size) { it }
private val arrayBuffer = IntBuffer.wrap(array)
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
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.complex.Complex
import space.kscience.kmath.complex.complex
import space.kscience.kmath.structures.MutableBuffer
@ -28,7 +28,7 @@ internal class BufferBenchmark {
}
}
companion object {
const val size: Int = 100
private companion object {
private const val size = 100
}
}

View File

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

View File

@ -1,64 +1,62 @@
package space.kscience.kmath.benchmarks
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.asm.compile
import space.kscience.kmath.ast.mstInField
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.expressionInField
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.Field
import space.kscience.kmath.operations.RealField
import space.kscience.kmath.operations.bindSymbol
import kotlin.random.Random
@State(Scope.Benchmark)
internal class ExpressionsInterpretersBenchmark {
private val algebra: Field<Double> = RealField
val x by symbol
@Benchmark
fun functionalExpression() {
fun functionalExpression(blackhole: Blackhole) {
val expr = algebra.expressionInField {
val x = bindSymbol(x)
x * const(2.0) + const(2.0) / x - const(16.0)
}
invokeAndSum(expr)
invokeAndSum(expr, blackhole)
}
@Benchmark
fun mstExpression() {
fun mstExpression(blackhole: Blackhole) {
val expr = algebra.mstInField {
val x = bindSymbol(x)
x * 2.0 + 2.0 / x - 16.0
}
invokeAndSum(expr)
invokeAndSum(expr, blackhole)
}
@Benchmark
fun asmExpression() {
fun asmExpression(blackhole: Blackhole) {
val expr = algebra.mstInField {
val x = bindSymbol(x)
x * 2.0 + 2.0 / x - 16.0
}.compile()
invokeAndSum(expr)
invokeAndSum(expr, blackhole)
}
@Benchmark
fun rawExpression() {
fun rawExpression(blackhole: Blackhole) {
val expr = Expression<Double> { args ->
val x = args.getValue(x)
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)
var sum = 0.0
@ -66,6 +64,11 @@ internal class ExpressionsInterpretersBenchmark {
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
import kotlinx.benchmark.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.commons.linear.CMMatrixContext
import space.kscience.kmath.commons.linear.CMMatrixContext.dot
import space.kscience.kmath.commons.linear.inverse
@ -18,7 +19,7 @@ import kotlin.random.Random
internal class LinearAlgebraBenchmark {
companion object {
val random = Random(1224)
val dim = 100
const val dim = 100
//creating invertible matrix
val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
@ -27,21 +28,21 @@ internal class LinearAlgebraBenchmark {
}
@Benchmark
fun kmathLupInversion() {
MatrixContext.real.inverseWithLup(matrix)
fun kmathLupInversion(blackhole: Blackhole) {
blackhole.consume(MatrixContext.real.inverseWithLup(matrix))
}
@Benchmark
fun cmLUPInversion() {
fun cmLUPInversion(blackhole: Blackhole) {
with(CMMatrixContext) {
inverse(matrix)
blackhole.consume(inverse(matrix))
}
}
@Benchmark
fun ejmlInverse() {
fun ejmlInverse(blackhole: Blackhole) {
with(EjmlMatrixContext) {
inverse(matrix)
blackhole.consume(inverse(matrix))
}
}
}

View File

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

View File

@ -1,51 +1,61 @@
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.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import space.kscience.kmath.nd.*
import space.kscience.kmath.nd.NDAlgebra
import space.kscience.kmath.nd.NDStructure
import space.kscience.kmath.nd.auto
import space.kscience.kmath.nd.real
import space.kscience.kmath.operations.RealField
import space.kscience.kmath.viktor.ViktorNDField
@State(Scope.Benchmark)
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
fun automaticFieldAddition() {
fun automaticFieldAddition(blackhole: Blackhole) {
with(autoField) {
var res: NDStructure<Double> = one
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
}
@Benchmark
fun realFieldAddition() {
fun realFieldAddition(blackhole: Blackhole) {
with(realField) {
var res: NDStructure<Double> = one
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
}
@Benchmark
fun viktorFieldAddition() {
fun viktorFieldAddition(blackhole: Blackhole) {
with(viktorField) {
var res = one
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
}
@Benchmark
fun rawViktor() {
fun rawViktor(blackhole: Blackhole) {
val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim))
var 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
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import org.jetbrains.bio.viktor.F64Array
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import space.kscience.kmath.nd.*
import space.kscience.kmath.nd.NDAlgebra
import space.kscience.kmath.nd.auto
import space.kscience.kmath.nd.real
import space.kscience.kmath.operations.RealField
import space.kscience.kmath.viktor.ViktorNDField
@State(Scope.Benchmark)
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
fun realFieldLog() {
fun realFieldLog(blackhole: Blackhole) {
with(realField) {
val fortyTwo = produce { 42.0 }
var res = one
repeat(n) { res = ln(fortyTwo) }
blackhole.consume(res)
}
}
@Benchmark
fun viktorFieldLog() {
fun viktorFieldLog(blackhole: Blackhole) {
with(viktorField) {
val fortyTwo = produce { 42.0 }
var res = one
repeat(n) { res = ln(fortyTwo) }
blackhole.consume(res)
}
}
@Benchmark
fun rawViktorLog() {
fun rawViktorLog(blackhole: Blackhole) {
val fortyTwo = F64Array.full(dim, dim, init = 42.0)
var res: F64Array
repeat(n) {
res = fortyTwo.log()
lateinit var res: F64Array
repeat(n) { 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))
}
}