2024-08-21 11:56:05 +03:00
|
|
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
|
|
|
import com.fasterxml.jackson.module.kotlin.readValue
|
|
|
|
import kotlinx.benchmark.gradle.BenchmarksExtension
|
|
|
|
import java.time.LocalDateTime
|
|
|
|
import java.time.ZoneId
|
|
|
|
import java.time.format.DateTimeFormatter
|
|
|
|
import java.time.format.DateTimeFormatterBuilder
|
|
|
|
import java.time.format.SignStyle
|
|
|
|
import java.time.temporal.ChronoField.*
|
|
|
|
import java.util.*
|
2021-06-15 09:18:40 +03:00
|
|
|
|
2021-04-16 22:43:10 +03:00
|
|
|
plugins {
|
|
|
|
kotlin("multiplatform")
|
2022-12-31 15:02:52 +03:00
|
|
|
alias(spclibs.plugins.kotlin.plugin.allopen)
|
2024-08-21 11:56:05 +03:00
|
|
|
alias(spclibs.plugins.kotlinx.benchmark)
|
2021-04-16 22:43:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
|
|
|
sourceSets.register("benchmarks")
|
|
|
|
|
|
|
|
repositories {
|
|
|
|
mavenCentral()
|
|
|
|
}
|
|
|
|
|
|
|
|
kotlin {
|
|
|
|
jvm()
|
|
|
|
|
2022-01-25 19:02:35 +03:00
|
|
|
js(IR) {
|
|
|
|
nodejs()
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:43:10 +03:00
|
|
|
sourceSets {
|
2022-01-25 19:02:35 +03:00
|
|
|
all {
|
|
|
|
languageSettings {
|
|
|
|
progressiveMode = true
|
2023-05-12 20:57:55 +03:00
|
|
|
optIn("kotlin.contracts.ExperimentalContracts")
|
|
|
|
optIn("kotlin.ExperimentalUnsignedTypes")
|
|
|
|
optIn("space.kscience.kmath.UnstableKMathAPI")
|
2022-01-25 19:02:35 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:43:10 +03:00
|
|
|
val commonMain by getting {
|
|
|
|
dependencies {
|
|
|
|
implementation(project(":kmath-ast"))
|
|
|
|
implementation(project(":kmath-core"))
|
|
|
|
implementation(project(":kmath-coroutines"))
|
|
|
|
implementation(project(":kmath-complex"))
|
|
|
|
implementation(project(":kmath-stat"))
|
|
|
|
implementation(project(":kmath-dimensions"))
|
|
|
|
implementation(project(":kmath-for-real"))
|
2021-10-06 12:25:32 +03:00
|
|
|
implementation(project(":kmath-tensors"))
|
2022-08-04 09:54:59 +03:00
|
|
|
implementation(project(":kmath-multik"))
|
2024-08-09 10:22:37 +03:00
|
|
|
implementation(libs.multik.default)
|
2022-12-31 15:02:52 +03:00
|
|
|
implementation(spclibs.kotlinx.benchmark.runtime)
|
2021-04-16 22:43:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
val jvmMain by getting {
|
|
|
|
dependencies {
|
|
|
|
implementation(project(":kmath-commons"))
|
|
|
|
implementation(project(":kmath-ejml"))
|
|
|
|
implementation(project(":kmath-nd4j"))
|
|
|
|
implementation(project(":kmath-kotlingrad"))
|
|
|
|
implementation(project(":kmath-viktor"))
|
2022-01-25 19:02:35 +03:00
|
|
|
implementation(project(":kmath-jafama"))
|
2022-02-17 22:46:17 +03:00
|
|
|
implementation(projects.kmath.kmathTensorflow)
|
|
|
|
implementation("org.tensorflow:tensorflow-core-platform:0.4.0")
|
2021-07-03 13:11:47 +03:00
|
|
|
implementation("org.nd4j:nd4j-native:1.0.0-M1")
|
2021-04-16 22:43:10 +03:00
|
|
|
// uncomment if your system supports AVX2
|
|
|
|
// val os = System.getProperty("os.name")
|
|
|
|
//
|
|
|
|
// if (System.getProperty("os.arch") in arrayOf("x86_64", "amd64")) when {
|
|
|
|
// os.startsWith("Windows") -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:windows-x86_64-avx2")
|
|
|
|
// os == "Linux" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:linux-x86_64-avx2")
|
|
|
|
// os == "Mac OS X" -> implementation("org.nd4j:nd4j-native:1.0.0-beta7:macosx-x86_64-avx2")
|
|
|
|
// } else
|
|
|
|
// implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Configure benchmark
|
|
|
|
benchmark {
|
|
|
|
// Setup configurations
|
|
|
|
targets {
|
|
|
|
register("jvm")
|
2024-07-07 11:02:49 +03:00
|
|
|
register("js")
|
2021-04-16 22:43:10 +03:00
|
|
|
}
|
|
|
|
|
2021-04-20 17:39:45 +03:00
|
|
|
fun kotlinx.benchmark.gradle.BenchmarkConfiguration.commonConfiguration() {
|
2021-11-15 18:42:00 +03:00
|
|
|
warmups = 2
|
2021-04-20 17:39:45 +03:00
|
|
|
iterations = 5
|
2021-11-15 18:42:00 +03:00
|
|
|
iterationTime = 2000
|
2021-04-20 17:39:45 +03:00
|
|
|
iterationTimeUnit = "ms"
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:43:10 +03:00
|
|
|
configurations.register("buffer") {
|
2021-04-20 17:39:45 +03:00
|
|
|
commonConfiguration()
|
2021-04-16 22:43:10 +03:00
|
|
|
include("BufferBenchmark")
|
|
|
|
}
|
|
|
|
|
2021-10-06 12:25:32 +03:00
|
|
|
configurations.register("nd") {
|
|
|
|
commonConfiguration()
|
|
|
|
include("NDFieldBenchmark")
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:43:10 +03:00
|
|
|
configurations.register("dot") {
|
2021-04-20 17:39:45 +03:00
|
|
|
commonConfiguration()
|
2021-04-16 22:43:10 +03:00
|
|
|
include("DotBenchmark")
|
|
|
|
}
|
|
|
|
|
|
|
|
configurations.register("expressions") {
|
2022-01-25 19:02:35 +03:00
|
|
|
// Some extra precision
|
|
|
|
warmups = 2
|
|
|
|
iterations = 10
|
2022-01-26 16:33:44 +03:00
|
|
|
iterationTime = 10
|
|
|
|
iterationTimeUnit = "s"
|
|
|
|
outputTimeUnit = "s"
|
2021-04-16 22:43:10 +03:00
|
|
|
include("ExpressionsInterpretersBenchmark")
|
|
|
|
}
|
|
|
|
|
|
|
|
configurations.register("matrixInverse") {
|
2021-04-20 17:39:45 +03:00
|
|
|
commonConfiguration()
|
2021-04-16 22:43:10 +03:00
|
|
|
include("MatrixInverseBenchmark")
|
|
|
|
}
|
|
|
|
|
|
|
|
configurations.register("bigInt") {
|
2021-04-20 17:39:45 +03:00
|
|
|
commonConfiguration()
|
2021-04-16 22:43:10 +03:00
|
|
|
include("BigIntBenchmark")
|
|
|
|
}
|
2021-06-08 16:49:55 +03:00
|
|
|
|
|
|
|
configurations.register("jafamaDouble") {
|
|
|
|
commonConfiguration()
|
|
|
|
include("JafamaBenchmark")
|
|
|
|
}
|
2021-09-21 21:24:27 +03:00
|
|
|
|
2022-02-20 02:21:52 +03:00
|
|
|
configurations.register("tensorAlgebra") {
|
|
|
|
commonConfiguration()
|
|
|
|
include("TensorAlgebraBenchmark")
|
|
|
|
}
|
|
|
|
|
2021-09-21 21:24:27 +03:00
|
|
|
configurations.register("viktor") {
|
|
|
|
commonConfiguration()
|
|
|
|
include("ViktorBenchmark")
|
|
|
|
}
|
|
|
|
|
|
|
|
configurations.register("viktorLog") {
|
|
|
|
commonConfiguration()
|
|
|
|
include("ViktorLogBenchmark")
|
|
|
|
}
|
2023-02-03 19:32:53 +03:00
|
|
|
|
|
|
|
configurations.register("integration") {
|
|
|
|
commonConfiguration()
|
|
|
|
include("IntegrationBenchmark")
|
|
|
|
}
|
2021-04-16 22:43:10 +03:00
|
|
|
}
|
|
|
|
|
2024-06-04 10:31:42 +03:00
|
|
|
kotlin {
|
|
|
|
jvmToolchain(11)
|
|
|
|
compilerOptions {
|
|
|
|
optIn.addAll(
|
|
|
|
"space.kscience.kmath.UnstableKMathAPI"
|
|
|
|
)
|
2021-04-16 22:43:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-21 11:56:05 +03:00
|
|
|
|
|
|
|
private data class JmhReport(
|
|
|
|
val jmhVersion: String,
|
|
|
|
val benchmark: String,
|
|
|
|
val mode: String,
|
|
|
|
val threads: Int,
|
|
|
|
val forks: Int,
|
|
|
|
val jvm: String,
|
|
|
|
val jvmArgs: List<String>,
|
|
|
|
val jdkVersion: String,
|
|
|
|
val vmName: String,
|
|
|
|
val vmVersion: String,
|
|
|
|
val warmupIterations: Int,
|
|
|
|
val warmupTime: String,
|
|
|
|
val warmupBatchSize: Int,
|
|
|
|
val measurementIterations: Int,
|
|
|
|
val measurementTime: String,
|
|
|
|
val measurementBatchSize: Int,
|
|
|
|
val params: Map<String, String> = emptyMap(),
|
|
|
|
val primaryMetric: PrimaryMetric,
|
|
|
|
val secondaryMetrics: Map<String, SecondaryMetric>,
|
|
|
|
) {
|
|
|
|
interface Metric {
|
|
|
|
val score: Double
|
|
|
|
val scoreError: Double
|
|
|
|
val scoreConfidence: List<Double>
|
|
|
|
val scorePercentiles: Map<Double, Double>
|
|
|
|
val scoreUnit: String
|
|
|
|
}
|
|
|
|
|
|
|
|
data class PrimaryMetric(
|
|
|
|
override val score: Double,
|
|
|
|
override val scoreError: Double,
|
|
|
|
override val scoreConfidence: List<Double>,
|
|
|
|
override val scorePercentiles: Map<Double, Double>,
|
|
|
|
override val scoreUnit: String,
|
|
|
|
val rawDataHistogram: List<List<List<List<Double>>>>? = null,
|
|
|
|
val rawData: List<List<Double>>? = null,
|
|
|
|
) : Metric
|
|
|
|
|
|
|
|
data class SecondaryMetric(
|
|
|
|
override val score: Double,
|
|
|
|
override val scoreError: Double,
|
|
|
|
override val scoreConfidence: List<Double>,
|
|
|
|
override val scorePercentiles: Map<Double, Double>,
|
|
|
|
override val scoreUnit: String,
|
|
|
|
val rawData: List<List<Double>>,
|
|
|
|
) : Metric
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:43:10 +03:00
|
|
|
readme {
|
2022-07-29 15:58:02 +03:00
|
|
|
maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
|
2021-06-15 09:18:40 +03:00
|
|
|
|
2024-08-21 11:56:05 +03:00
|
|
|
val jsonMapper = jacksonObjectMapper()
|
|
|
|
|
|
|
|
|
|
|
|
val ISO_DATE_TIME: DateTimeFormatter = DateTimeFormatterBuilder().run {
|
|
|
|
parseCaseInsensitive()
|
|
|
|
appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
|
|
|
|
appendLiteral('-')
|
|
|
|
appendValue(MONTH_OF_YEAR, 2)
|
|
|
|
appendLiteral('-')
|
|
|
|
appendValue(DAY_OF_MONTH, 2)
|
|
|
|
appendLiteral('T')
|
|
|
|
appendValue(HOUR_OF_DAY, 2)
|
|
|
|
appendLiteral('.')
|
|
|
|
appendValue(MINUTE_OF_HOUR, 2)
|
|
|
|
optionalStart()
|
|
|
|
appendLiteral('.')
|
|
|
|
appendValue(SECOND_OF_MINUTE, 2)
|
|
|
|
optionalStart()
|
|
|
|
appendFraction(NANO_OF_SECOND, 0, 9, true)
|
|
|
|
optionalStart()
|
|
|
|
appendOffsetId()
|
|
|
|
optionalStart()
|
|
|
|
appendLiteral('[')
|
|
|
|
parseCaseSensitive()
|
|
|
|
appendZoneRegionId()
|
|
|
|
appendLiteral(']')
|
|
|
|
toFormatter()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun noun(number: Number, singular: String, plural: String) = if (number.toLong() == 1L) singular else plural
|
|
|
|
|
|
|
|
extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg ->
|
|
|
|
property("benchmark${cfg.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}") {
|
|
|
|
val launches = layout.buildDirectory.dir("reports/benchmarks/${cfg.name}").get()
|
|
|
|
|
|
|
|
val resDirectory = launches.files().maxByOrNull {
|
|
|
|
LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant()
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resDirectory == null || !(resDirectory.resolve("jvm.json")).exists()) {
|
|
|
|
"> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**."
|
|
|
|
} else {
|
|
|
|
val reports: List<JmhReport> =
|
|
|
|
jsonMapper.readValue<List<JmhReport>>(resDirectory.resolve("jvm.json"))
|
|
|
|
|
|
|
|
buildString {
|
|
|
|
appendLine("<details>")
|
|
|
|
appendLine("<summary>")
|
|
|
|
appendLine("Report for benchmark configuration <code>${cfg.name}</code>")
|
|
|
|
appendLine("</summary>")
|
|
|
|
appendLine()
|
|
|
|
val first = reports.first()
|
|
|
|
|
|
|
|
appendLine("* Run on ${first.vmName} (build ${first.vmVersion}) with Java process:")
|
|
|
|
appendLine()
|
|
|
|
appendLine("```")
|
|
|
|
appendLine(
|
|
|
|
"${first.jvm} ${
|
|
|
|
first.jvmArgs.joinToString(" ")
|
|
|
|
}"
|
|
|
|
)
|
|
|
|
appendLine("```")
|
|
|
|
|
|
|
|
appendLine(
|
|
|
|
"* JMH ${first.jmhVersion} was used in `${first.mode}` mode with ${first.warmupIterations} warmup ${
|
|
|
|
noun(first.warmupIterations, "iteration", "iterations")
|
|
|
|
} by ${first.warmupTime} and ${first.measurementIterations} measurement ${
|
|
|
|
noun(first.measurementIterations, "iteration", "iterations")
|
|
|
|
} by ${first.measurementTime}."
|
|
|
|
)
|
|
|
|
|
|
|
|
appendLine()
|
|
|
|
appendLine("| Benchmark | Score |")
|
|
|
|
appendLine("|:---------:|:-----:|")
|
|
|
|
|
|
|
|
reports.forEach { report ->
|
|
|
|
appendLine("|`${report.benchmark}`|${report.primaryMetric.score} ± ${report.primaryMetric.scoreError} ${report.primaryMetric.scoreUnit}|")
|
|
|
|
}
|
|
|
|
|
|
|
|
appendLine("</details>")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|