diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index fa72dc8ee..686c491b9 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -36,6 +36,7 @@ kotlin { implementation(project(":kmath-dimensions")) implementation(project(":kmath-for-real")) implementation(project(":kmath-jafama")) + implementation(project(":kmath-tensors")) implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.1") } } @@ -81,6 +82,11 @@ benchmark { include("BufferBenchmark") } + configurations.register("nd") { + commonConfiguration() + include("NDFieldBenchmark") + } + configurations.register("dot") { commonConfiguration() include("DotBenchmark") diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt index f72bc3ba0..76fec05d3 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt @@ -12,44 +12,63 @@ import kotlinx.benchmark.State import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.autoNdAlgebra import space.kscience.kmath.nd.ndAlgebra +import space.kscience.kmath.nd4j.nd4j import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.structures.Buffer +import space.kscience.kmath.tensors.core.DoubleTensor +import space.kscience.kmath.tensors.core.ones +import space.kscience.kmath.tensors.core.tensorAlgebra @State(Scope.Benchmark) internal class NDFieldBenchmark { @Benchmark - fun autoFieldAdd(blackhole: Blackhole) { - with(autoField) { - var res: StructureND = one - repeat(n) { res += one } - blackhole.consume(res) - } + fun autoFieldAdd(blackhole: Blackhole) = with(autoField) { + var res: StructureND = one + repeat(n) { res += one } + blackhole.consume(res) } @Benchmark - fun specializedFieldAdd(blackhole: Blackhole) { - with(specializedField) { - var res: StructureND = one - repeat(n) { res += 1.0 } - blackhole.consume(res) - } + fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) { + var res: StructureND = one + repeat(n) { res += 1.0 } + blackhole.consume(res) } - @Benchmark - fun boxingFieldAdd(blackhole: Blackhole) { - with(genericField) { - var res: StructureND = one - repeat(n) { res += 1.0 } - blackhole.consume(res) - } + fun boxingFieldAdd(blackhole: Blackhole) = with(genericField) { + var res: StructureND = one + repeat(n) { res += 1.0 } + blackhole.consume(res) } + @Benchmark + fun tensorAdd(blackhole: Blackhole) = with(Double.tensorAlgebra) { + var res: DoubleTensor = ones(dim, dim) + repeat(n) { res = res + 1.0 } + blackhole.consume(res) + } + + @Benchmark + fun tensorInPlaceAdd(blackhole: Blackhole) = with(Double.tensorAlgebra) { + val res: DoubleTensor = ones(dim, dim) + repeat(n) { res += 1.0 } + blackhole.consume(res) + } + +// @Benchmark +// fun nd4jAdd(blackhole: Blackhole) = with(nd4jField) { +// var res: StructureND = one +// repeat(n) { res += 1.0 } +// blackhole.consume(res) +// } + private companion object { private const val dim = 1000 private const val n = 100 private val autoField = DoubleField.autoNdAlgebra(dim, dim) private val specializedField = DoubleField.ndAlgebra(dim, dim) private val genericField = DoubleField.ndAlgebra(Buffer.Companion::boxing, dim, dim) + private val nd4jField = DoubleField.nd4j(dim, dim) } } diff --git a/kmath-nd4j/build.gradle.kts b/kmath-nd4j/build.gradle.kts index dcb6f1b4a..09264501f 100644 --- a/kmath-nd4j/build.gradle.kts +++ b/kmath-nd4j/build.gradle.kts @@ -9,7 +9,7 @@ dependencies { api(project(":kmath-tensors")) api("org.nd4j:nd4j-api:1.0.0-M1") testImplementation("org.nd4j:nd4j-native-platform:1.0.0-M1") - testImplementation("org.slf4j:slf4j-simple:1.7.31") + testImplementation("org.slf4j:slf4j-simple:1.7.32") } readme { diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt index 54df31556..b604bf5f2 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jArrayAlgebra.kt @@ -45,7 +45,6 @@ public sealed interface Nd4jArrayAlgebra> : AlgebraND.map(transform: C.(T) -> T): Nd4jArrayStructure { val newStruct = ndArray.dup().wrap() newStruct.elements().forEach { (idx, value) -> newStruct[idx] = elementContext.transform(value) } @@ -265,6 +264,8 @@ public class DoubleNd4jArrayField(override val shape: IntArray) : Nd4jArrayExten } } +public fun DoubleField.nd4j(vararg shape: Int): DoubleNd4jArrayField = DoubleNd4jArrayField(intArrayOf(*shape)) + /** * Represents [FieldND] over [Nd4jArrayStructure] of [Float]. */ diff --git a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt index 0ac37e19b..ee9251dd1 100644 --- a/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt +++ b/kmath-nd4j/src/main/kotlin/space/kscience/kmath/nd4j/Nd4jTensorAlgebra.kt @@ -158,7 +158,6 @@ public object DoubleNd4jTensorAlgebra : Nd4jTensorAlgebra { if (shape contentEquals intArrayOf(1)) ndArray.getDouble(0) else null // TODO rewrite - @PerformancePitfall override fun diagonalEmbedding( diagonalEntries: Tensor, offset: Int, diff --git a/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt new file mode 100644 index 000000000..b73f95054 --- /dev/null +++ b/kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/tensorAlgebraExtensions.kt @@ -0,0 +1,8 @@ +/* + * 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 file. + */ + +package space.kscience.kmath.tensors.core + +public fun DoubleTensorAlgebra.ones(vararg shape: Int): DoubleTensor = ones(intArrayOf(*shape)) \ No newline at end of file