forked from kscience/kmath
Merge pull request #451 from mipt-npm/commandertvis/js-benchmark
Make JS benchmarks of expressions
This commit is contained in:
commit
2e13d518f6
@ -13,13 +13,22 @@ sourceSets.register("benchmarks")
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven("https://repo.kotlin.link")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvm()
|
jvm()
|
||||||
|
|
||||||
|
js(IR) {
|
||||||
|
nodejs()
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
all {
|
||||||
|
languageSettings {
|
||||||
|
progressiveMode = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":kmath-ast"))
|
implementation(project(":kmath-ast"))
|
||||||
@ -29,9 +38,8 @@ kotlin {
|
|||||||
implementation(project(":kmath-stat"))
|
implementation(project(":kmath-stat"))
|
||||||
implementation(project(":kmath-dimensions"))
|
implementation(project(":kmath-dimensions"))
|
||||||
implementation(project(":kmath-for-real"))
|
implementation(project(":kmath-for-real"))
|
||||||
implementation(project(":kmath-jafama"))
|
|
||||||
implementation(project(":kmath-tensors"))
|
implementation(project(":kmath-tensors"))
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.1")
|
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.2")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +50,7 @@ kotlin {
|
|||||||
implementation(project(":kmath-nd4j"))
|
implementation(project(":kmath-nd4j"))
|
||||||
implementation(project(":kmath-kotlingrad"))
|
implementation(project(":kmath-kotlingrad"))
|
||||||
implementation(project(":kmath-viktor"))
|
implementation(project(":kmath-viktor"))
|
||||||
|
implementation(project(":kmath-jafama"))
|
||||||
implementation(project(":kmath-multik"))
|
implementation(project(":kmath-multik"))
|
||||||
implementation("org.nd4j:nd4j-native:1.0.0-M1")
|
implementation("org.nd4j:nd4j-native:1.0.0-M1")
|
||||||
// uncomment if your system supports AVX2
|
// uncomment if your system supports AVX2
|
||||||
@ -63,6 +72,7 @@ benchmark {
|
|||||||
// Setup configurations
|
// Setup configurations
|
||||||
targets {
|
targets {
|
||||||
register("jvm")
|
register("jvm")
|
||||||
|
register("js")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
|
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
|
||||||
@ -88,7 +98,12 @@ benchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configurations.register("expressions") {
|
configurations.register("expressions") {
|
||||||
commonConfiguration()
|
// Some extra precision
|
||||||
|
warmups = 2
|
||||||
|
iterations = 10
|
||||||
|
iterationTime = 10
|
||||||
|
iterationTimeUnit = "s"
|
||||||
|
outputTimeUnit = "s"
|
||||||
include("ExpressionsInterpretersBenchmark")
|
include("ExpressionsInterpretersBenchmark")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +140,6 @@ afterEvaluate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
kotlin.sourceSets.all {
|
kotlin.sourceSets.all {
|
||||||
with(languageSettings) {
|
with(languageSettings) {
|
||||||
optIn("kotlin.contracts.ExperimentalContracts")
|
optIn("kotlin.contracts.ExperimentalContracts")
|
||||||
@ -141,7 +155,6 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
|
import kotlinx.benchmark.Benchmark
|
||||||
|
import kotlinx.benchmark.Blackhole
|
||||||
|
import kotlinx.benchmark.Scope
|
||||||
|
import kotlinx.benchmark.State
|
||||||
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.operations.Algebra
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import kotlin.math.sin
|
||||||
|
import kotlin.random.Random
|
||||||
|
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
|
||||||
|
import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
|
||||||
|
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
class ExpressionsInterpretersBenchmark {
|
||||||
|
/**
|
||||||
|
* Benchmark case for [Expression] created with [expressionInExtendedField].
|
||||||
|
*/
|
||||||
|
@Benchmark
|
||||||
|
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmark case for [Expression] created with [toExpression].
|
||||||
|
*/
|
||||||
|
@Benchmark
|
||||||
|
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmark case for [Expression] created with [compileToExpression].
|
||||||
|
*/
|
||||||
|
@Benchmark
|
||||||
|
fun wasmExpression(blackhole: Blackhole) = invokeAndSum(wasm, blackhole)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmark case for [Expression] created with [compileToExpression].
|
||||||
|
*/
|
||||||
|
@Benchmark
|
||||||
|
fun estreeExpression(blackhole: Blackhole) = invokeAndSum(estree, blackhole)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmark case for [Expression] implemented manually with `kotlin.math` functions.
|
||||||
|
*/
|
||||||
|
@Benchmark
|
||||||
|
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmark case for direct computation w/o [Expression].
|
||||||
|
*/
|
||||||
|
@Benchmark
|
||||||
|
fun justCalculate(blackhole: Blackhole) {
|
||||||
|
val random = Random(0)
|
||||||
|
var sum = 0.0
|
||||||
|
|
||||||
|
repeat(times) {
|
||||||
|
val x = random.nextDouble()
|
||||||
|
sum += x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
blackhole.consume(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
||||||
|
val random = Random(0)
|
||||||
|
var sum = 0.0
|
||||||
|
val m = HashMap<Symbol, Double>()
|
||||||
|
|
||||||
|
repeat(times) {
|
||||||
|
m[x] = random.nextDouble()
|
||||||
|
sum += expr(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
blackhole.consume(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private val x by symbol
|
||||||
|
private const val times = 1_000_000
|
||||||
|
|
||||||
|
private val functional = DoubleField.expression {
|
||||||
|
val x = bindSymbol(Symbol.x)
|
||||||
|
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val node = MstExtendedField {
|
||||||
|
x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mst = node.toExpression(DoubleField)
|
||||||
|
private val wasm = node.wasmCompileToExpression(DoubleField)
|
||||||
|
private val estree = node.estreeCompileToExpression(DoubleField)
|
||||||
|
|
||||||
|
private val raw = Expression<Double> { args ->
|
||||||
|
val x = args[x]!!
|
||||||
|
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ repositories {
|
|||||||
|
|
||||||
val toolsVersion: String by extra
|
val toolsVersion: String by extra
|
||||||
val kotlinVersion = npmlibs.versions.kotlin.asProvider().get()
|
val kotlinVersion = npmlibs.versions.kotlin.asProvider().get()
|
||||||
val benchmarksVersion = npmlibs.versions.kotlinx.benchmark.get()
|
val benchmarksVersion = "0.4.2"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("ru.mipt.npm:gradle-tools:$toolsVersion")
|
api("ru.mipt.npm:gradle-tools:$toolsVersion")
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.*
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import kotlin.math.sin
|
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlin.test.Ignore
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.time.measureTime
|
|
||||||
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
|
|
||||||
import space.kscience.kmath.wasm.compileToExpression as wasmCompileToExpression
|
|
||||||
|
|
||||||
// TODO move to benchmarks when https://github.com/Kotlin/kotlinx-benchmark/pull/38 or similar feature is merged
|
|
||||||
@Ignore
|
|
||||||
internal class TestExecutionTime {
|
|
||||||
private companion object {
|
|
||||||
private const val times = 1_000_000
|
|
||||||
private val x by symbol
|
|
||||||
private val algebra = DoubleField
|
|
||||||
|
|
||||||
private val functional = algebra.expressionInExtendedField {
|
|
||||||
bindSymbol(x) * const(2.0) + const(2.0) / bindSymbol(x) - const(16.0) / sin(bindSymbol(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
private val node = MstExtendedField {
|
|
||||||
x * number(2.0) + number(2.0) / x - number(16.0) / sin(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val mst = node.toExpression(algebra)
|
|
||||||
private val wasm = node.wasmCompileToExpression(algebra)
|
|
||||||
private val estree = node.estreeCompileToExpression(algebra)
|
|
||||||
|
|
||||||
// In JavaScript, the expression below is implemented like
|
|
||||||
// _no_name_provided__125.prototype.invoke_178 = function (args) {
|
|
||||||
// var tmp = getValue(args, raw$_get_x__3(this._$x$delegate_2)) * 2.0 + 2.0 / getValue(args, raw$_get_x__3(this._$x$delegate_2));
|
|
||||||
// var tmp0_sin_0_5 = getValue(args, raw$_get_x__3(this._$x$delegate_2));
|
|
||||||
// return tmp - 16.0 / Math.sin(tmp0_sin_0_5);
|
|
||||||
// };
|
|
||||||
|
|
||||||
private val raw = Expression<Double> { args ->
|
|
||||||
val x = args[x]!!
|
|
||||||
algebra { x * 2.0 + 2.0 / x - 16.0 / sin(x) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val justCalculate = { args: dynamic ->
|
|
||||||
val x = args[x].unsafeCast<Double>()
|
|
||||||
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun invokeAndSum(name: String, expr: Expression<Double>) {
|
|
||||||
println(name)
|
|
||||||
val rng = Random(0)
|
|
||||||
var sum = 0.0
|
|
||||||
measureTime {
|
|
||||||
repeat(times) { sum += expr(x to rng.nextDouble()) }
|
|
||||||
}.also(::println)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [Expression] created with [expressionInExtendedField].
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
fun functionalExpression() = invokeAndSum("functional", functional)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [Expression] created with [mstExpression].
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
fun mstExpression() = invokeAndSum("mst", mst)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [Expression] created with [wasmCompileToExpression].
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
fun wasmExpression() = invokeAndSum("wasm", wasm)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [Expression] created with [estreeCompileToExpression].
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
fun estreeExpression() = invokeAndSum("estree", wasm)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [Expression] implemented manually with `kotlin.math`.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
fun rawExpression() = invokeAndSum("raw", raw)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Direct computation w/o [Expression].
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
fun justCalculateExpression() {
|
|
||||||
println("justCalculate")
|
|
||||||
val rng = Random(0)
|
|
||||||
var sum = 0.0
|
|
||||||
measureTime {
|
|
||||||
repeat(times) {
|
|
||||||
val arg = rng.nextDouble()
|
|
||||||
val o = js("{}")
|
|
||||||
o["x"] = arg
|
|
||||||
sum += justCalculate(o)
|
|
||||||
}
|
|
||||||
}.also(::println)
|
|
||||||
}
|
|
||||||
}
|
|
2059
kotlin-js-store/yarn.lock
Normal file
2059
kotlin-js-store/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user