Viktor prototype

This commit is contained in:
Alexander Nozik 2019-12-08 15:48:25 +03:00
parent bf2f4db468
commit f9836a6477
9 changed files with 160 additions and 22 deletions

View File

@ -4,7 +4,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
java
kotlin("jvm")
kotlin("plugin.allopen") version "1.3.60"
kotlin("plugin.allopen") version "1.3.61"
id("kotlinx.benchmark") version "0.2.0-dev-5"
}
@ -29,6 +29,7 @@ dependencies {
implementation(project(":kmath-coroutines"))
implementation(project(":kmath-commons"))
implementation(project(":kmath-koma"))
implementation(project(":kmath-viktor"))
implementation("com.kyonifer:koma-core-ejml:0.12")
implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:${Scientifik.ioVersion}")

View File

@ -4,7 +4,13 @@ import kotlinx.coroutines.GlobalScope
import scientifik.kmath.operations.RealField
import kotlin.system.measureTimeMillis
fun main(args: Array<String>) {
internal inline fun measureAndPrint(title: String, block: () -> Unit) {
val time = measureTimeMillis(block)
println("$title completed in $time millis")
}
fun main() {
val dim = 1000
val n = 1000
@ -15,8 +21,7 @@ fun main(args: Array<String>) {
//A generic boxing field. It should be used for objects, not primitives.
val genericField = NDField.boxing(RealField, dim, dim)
val autoTime = measureTimeMillis {
measureAndPrint("Automatic field addition") {
autoField.run {
var res = one
repeat(n) {
@ -25,18 +30,14 @@ fun main(args: Array<String>) {
}
}
println("Automatic field addition completed in $autoTime millis")
val elementTime = measureTimeMillis {
measureAndPrint("Element addition"){
var res = genericField.one
repeat(n) {
res += 1.0
}
}
println("Element addition completed in $elementTime millis")
val specializedTime = measureTimeMillis {
measureAndPrint("Specialized addition") {
specializedField.run {
var res: NDBuffer<Double> = one
repeat(n) {
@ -45,10 +46,7 @@ fun main(args: Array<String>) {
}
}
println("Specialized addition completed in $specializedTime millis")
val lazyTime = measureTimeMillis {
measureAndPrint("Lazy addition") {
val res = specializedField.one.mapAsync(GlobalScope) {
var c = 0.0
repeat(n) {
@ -60,9 +58,7 @@ fun main(args: Array<String>) {
res.elements().forEach { it.second }
}
println("Lazy addition completed in $lazyTime millis")
val genericTime = measureTimeMillis {
measureAndPrint("Generic addition") {
//genericField.run(action)
genericField.run {
var res: NDBuffer<Double> = one
@ -72,6 +68,4 @@ fun main(args: Array<String>) {
}
}
println("Generic addition completed in $genericTime millis")
}

View File

@ -0,0 +1,42 @@
package scientifik.kmath.structures
import org.jetbrains.bio.viktor.F64Array
import scientifik.kmath.operations.RealField
import scientifik.kmath.viktor.ViktorNDField
fun main() {
val dim = 1000
val n = 400
// automatically build context most suited for given type.
val autoField = NDField.auto(RealField, dim, dim)
val viktorField = ViktorNDField(intArrayOf(dim, dim))
measureAndPrint("Automatic field addition") {
autoField.run {
var res = one
repeat(n) {
res += 1.0
}
}
}
measureAndPrint("Raw Viktor") {
val one = F64Array.full(init = 1.0, shape = *intArrayOf(dim, dim))
var res = one
repeat(n) {
res = res + one
}
}
measureAndPrint("Viktor field addition") {
viktorField.run {
var res = one
repeat(n) {
res += 1.0
}
}
}
}

View File

@ -9,6 +9,4 @@ dependencies {
api(project(":kmath-coroutines"))
api(project(":kmath-prob"))
api("org.apache.commons:commons-math3:3.6.1")
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}

View File

@ -2,7 +2,6 @@ package scientifik.kmath.structures
import scientifik.kmath.operations.*
interface ExtendedNDField<T : Any, F, N : NDStructure<T>> :
NDField<T, F, N>,
TrigonometricOperations<N>,

View File

@ -0,0 +1,10 @@
plugins {
id("scientifik.jvm")
}
description = "Binding for https://github.com/JetBrains-Research/viktor"
dependencies {
api(project(":kmath-core"))
api("org.jetbrains.bio:viktor:1.0.1")
}

View File

@ -0,0 +1,20 @@
package scientifik.kmath.viktor
import org.jetbrains.bio.viktor.F64FlatArray
import scientifik.kmath.structures.MutableBuffer
@Suppress("NOTHING_TO_INLINE", "OVERRIDE_BY_INLINE")
inline class ViktorBuffer(val flatArray: F64FlatArray) : MutableBuffer<Double> {
override val size: Int get() = flatArray.size
override inline fun get(index: Int): Double = flatArray[index]
override inline fun set(index: Int, value: Double) {
flatArray[index] = value
}
override fun copy(): MutableBuffer<Double> {
return ViktorBuffer(flatArray.copy().flatten())
}
override fun iterator(): Iterator<Double> = flatArray.data.iterator()
}

View File

@ -0,0 +1,73 @@
package scientifik.kmath.viktor
import org.jetbrains.bio.viktor.F64Array
import scientifik.kmath.operations.RealField
import scientifik.kmath.structures.DefaultStrides
import scientifik.kmath.structures.MutableNDStructure
import scientifik.kmath.structures.NDField
inline class ViktorNDStructure(val f64Buffer: F64Array) : MutableNDStructure<Double> {
override val shape: IntArray get() = f64Buffer.shape
override fun get(index: IntArray): Double = f64Buffer.get(*index)
override fun set(index: IntArray, value: Double) {
f64Buffer.set(value = value, indices = *index)
}
override fun elements(): Sequence<Pair<IntArray, Double>> {
return DefaultStrides(shape).indices().map { it to get(it) }
}
}
fun F64Array.asStructure(): ViktorNDStructure = ViktorNDStructure(this)
class ViktorNDField(override val shape: IntArray) : NDField<Double, RealField, ViktorNDStructure> {
override val zero: ViktorNDStructure
get() = F64Array.full(init = 0.0, shape = *shape).asStructure()
override val one: ViktorNDStructure
get() = F64Array.full(init = 1.0, shape = *shape).asStructure()
val strides = DefaultStrides(shape)
override val elementContext: RealField get() = RealField
override fun produce(initializer: RealField.(IntArray) -> Double): ViktorNDStructure = F64Array(*shape).apply {
this@ViktorNDField.strides.indices().forEach { index ->
set(value = RealField.initializer(index), indices = *index)
}
}.asStructure()
override fun map(arg: ViktorNDStructure, transform: RealField.(Double) -> Double): ViktorNDStructure =
F64Array(*shape).apply {
this@ViktorNDField.strides.indices().forEach { index ->
set(value = RealField.transform(arg[index]), indices = *index)
}
}.asStructure()
override fun mapIndexed(
arg: ViktorNDStructure,
transform: RealField.(index: IntArray, Double) -> Double
): ViktorNDStructure = F64Array(*shape).apply {
this@ViktorNDField.strides.indices().forEach { index ->
set(value = RealField.transform(index, arg[index]), indices = *index)
}
}.asStructure()
override fun combine(
a: ViktorNDStructure,
b: ViktorNDStructure,
transform: RealField.(Double, Double) -> Double
): ViktorNDStructure = F64Array(*shape).apply {
this@ViktorNDField.strides.indices().forEach { index ->
set(value = RealField.transform(a[index], b[index]), indices = *index)
}
}.asStructure()
override fun ViktorNDStructure.plus(b: ViktorNDStructure): ViktorNDStructure =
(f64Buffer + b.f64Buffer).asStructure()
override fun ViktorNDStructure.minus(b: ViktorNDStructure): ViktorNDStructure =
(f64Buffer - b.f64Buffer).asStructure()
}

View File

@ -33,6 +33,7 @@ include(
":kmath-coroutines",
":kmath-histograms",
":kmath-commons",
":kmath-viktor",
":kmath-koma",
":kmath-prob",
":kmath-io",