Viktor prototype
This commit is contained in:
parent
bf2f4db468
commit
f9836a6477
@ -4,7 +4,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|||||||
plugins {
|
plugins {
|
||||||
java
|
java
|
||||||
kotlin("jvm")
|
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"
|
id("kotlinx.benchmark") version "0.2.0-dev-5"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,6 +29,7 @@ dependencies {
|
|||||||
implementation(project(":kmath-coroutines"))
|
implementation(project(":kmath-coroutines"))
|
||||||
implementation(project(":kmath-commons"))
|
implementation(project(":kmath-commons"))
|
||||||
implementation(project(":kmath-koma"))
|
implementation(project(":kmath-koma"))
|
||||||
|
implementation(project(":kmath-viktor"))
|
||||||
implementation("com.kyonifer:koma-core-ejml:0.12")
|
implementation("com.kyonifer:koma-core-ejml:0.12")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:${Scientifik.ioVersion}")
|
implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:${Scientifik.ioVersion}")
|
||||||
|
|
||||||
|
@ -4,7 +4,13 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import scientifik.kmath.operations.RealField
|
import scientifik.kmath.operations.RealField
|
||||||
import kotlin.system.measureTimeMillis
|
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 dim = 1000
|
||||||
val n = 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.
|
//A generic boxing field. It should be used for objects, not primitives.
|
||||||
val genericField = NDField.boxing(RealField, dim, dim)
|
val genericField = NDField.boxing(RealField, dim, dim)
|
||||||
|
|
||||||
|
measureAndPrint("Automatic field addition") {
|
||||||
val autoTime = measureTimeMillis {
|
|
||||||
autoField.run {
|
autoField.run {
|
||||||
var res = one
|
var res = one
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
@ -25,18 +30,14 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Automatic field addition completed in $autoTime millis")
|
measureAndPrint("Element addition"){
|
||||||
|
|
||||||
val elementTime = measureTimeMillis {
|
|
||||||
var res = genericField.one
|
var res = genericField.one
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
res += 1.0
|
res += 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Element addition completed in $elementTime millis")
|
measureAndPrint("Specialized addition") {
|
||||||
|
|
||||||
val specializedTime = measureTimeMillis {
|
|
||||||
specializedField.run {
|
specializedField.run {
|
||||||
var res: NDBuffer<Double> = one
|
var res: NDBuffer<Double> = one
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
@ -45,10 +46,7 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Specialized addition completed in $specializedTime millis")
|
measureAndPrint("Lazy addition") {
|
||||||
|
|
||||||
|
|
||||||
val lazyTime = measureTimeMillis {
|
|
||||||
val res = specializedField.one.mapAsync(GlobalScope) {
|
val res = specializedField.one.mapAsync(GlobalScope) {
|
||||||
var c = 0.0
|
var c = 0.0
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
@ -60,9 +58,7 @@ fun main(args: Array<String>) {
|
|||||||
res.elements().forEach { it.second }
|
res.elements().forEach { it.second }
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Lazy addition completed in $lazyTime millis")
|
measureAndPrint("Generic addition") {
|
||||||
|
|
||||||
val genericTime = measureTimeMillis {
|
|
||||||
//genericField.run(action)
|
//genericField.run(action)
|
||||||
genericField.run {
|
genericField.run {
|
||||||
var res: NDBuffer<Double> = one
|
var res: NDBuffer<Double> = one
|
||||||
@ -72,6 +68,4 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Generic addition completed in $genericTime millis")
|
|
||||||
|
|
||||||
}
|
}
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,4 @@ dependencies {
|
|||||||
api(project(":kmath-coroutines"))
|
api(project(":kmath-coroutines"))
|
||||||
api(project(":kmath-prob"))
|
api(project(":kmath-prob"))
|
||||||
api("org.apache.commons:commons-math3:3.6.1")
|
api("org.apache.commons:commons-math3:3.6.1")
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test")
|
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
|
|
||||||
}
|
}
|
@ -2,7 +2,6 @@ package scientifik.kmath.structures
|
|||||||
|
|
||||||
import scientifik.kmath.operations.*
|
import scientifik.kmath.operations.*
|
||||||
|
|
||||||
|
|
||||||
interface ExtendedNDField<T : Any, F, N : NDStructure<T>> :
|
interface ExtendedNDField<T : Any, F, N : NDStructure<T>> :
|
||||||
NDField<T, F, N>,
|
NDField<T, F, N>,
|
||||||
TrigonometricOperations<N>,
|
TrigonometricOperations<N>,
|
||||||
|
10
kmath-viktor/build.gradle.kts
Normal file
10
kmath-viktor/build.gradle.kts
Normal 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")
|
||||||
|
}
|
@ -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()
|
||||||
|
}
|
@ -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()
|
||||||
|
}
|
@ -33,6 +33,7 @@ include(
|
|||||||
":kmath-coroutines",
|
":kmath-coroutines",
|
||||||
":kmath-histograms",
|
":kmath-histograms",
|
||||||
":kmath-commons",
|
":kmath-commons",
|
||||||
|
":kmath-viktor",
|
||||||
":kmath-koma",
|
":kmath-koma",
|
||||||
":kmath-prob",
|
":kmath-prob",
|
||||||
":kmath-io",
|
":kmath-io",
|
||||||
|
Loading…
Reference in New Issue
Block a user