Skip to content

Commit

Permalink
Merge branch 'master' into master-kotlin18
Browse files Browse the repository at this point in the history
# Conflicts:
#	build.gradle.kts
#	gradle/libs.versions.toml
#	ndarray/ndarray-core/src/jvmMain/kotlin/io/kinference/ndarray/arrays/memory/ModelArrayStorage.kt
  • Loading branch information
dmitriyb committed Sep 26, 2024
2 parents 9f1c206 + a8ff9d6 commit 5b44daf
Show file tree
Hide file tree
Showing 53 changed files with 903 additions and 636 deletions.
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ it is highly recommended to use KInference TensorFlow.js backend instead for mor
KInference Core dependency coordinates:
```kotlin
dependencies {
api("io.kinference", "inference-core", "0.2.22")
api("io.kinference", "inference-core", "0.2.23")
}
```

Expand All @@ -67,7 +67,7 @@ This backend is recommended for JavaScript projects.
TensorFlow.js backend dependency coordinates:
```kotlin
dependencies {
api("io.kinference", "inference-tfjs", "0.2.22")
api("io.kinference", "inference-tfjs", "0.2.23")
}
```

Expand All @@ -81,14 +81,14 @@ To check on the system requirements, visit the following [link](https://onnxrunt
ONNXRuntime CPU backend dependency coordinates:
```kotlin
dependencies {
api("io.kinference", "inference-ort", "0.2.22")
api("io.kinference", "inference-ort", "0.2.23")
}
```

ONNXRuntime GPU backend dependency coordinates:
```kotlin
dependencies {
api("io.kinference", "inference-ort-gpu", "0.2.22")
api("io.kinference", "inference-ort-gpu", "0.2.23")
}
```

Expand All @@ -104,7 +104,7 @@ Array adapter for the [kmath](https://github.com/SciProgCentre/kmath) library th
Dependency coordinates:
```kotlin
dependencies {
api("io.kinference", "adapter-kmath-{backend_name}", "0.2.22")
api("io.kinference", "adapter-kmath-{backend_name}", "0.2.23")
}
```

Expand All @@ -114,12 +114,12 @@ Array adapter for the [multik](https://github.com/Kotlin/multik) library that wo
Dependency coordinates:
```kotlin
dependencies {
api("io.kinference", "adapter-multik-{backend_name}", "0.2.22")
api("io.kinference", "adapter-multik-{backend_name}", "0.2.23")
}
```

## Getting started
Let us now walk through how to get started with KInference. The latest version of KInference is *0.2.22*
Let us now walk through how to get started with KInference. The latest version of KInference is *0.2.23*

### Setup dependencies repository

Expand All @@ -142,7 +142,7 @@ To enable the backend, you can add the chosen KInference runtime as a dependency

```kotlin
dependencies {
api("io.kinference", "inference-core", "0.2.22")
api("io.kinference", "inference-core", "0.2.23")
}
```

Expand All @@ -160,20 +160,20 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
api("io.kinference:inference-api:0.2.22")
api("io.kinference:ndarray-api:0.2.22")
api("io.kinference:inference-api:0.2.23")
api("io.kinference:ndarray-api:0.2.23")
}
}

val jvmMain by getting {
dependencies {
api("io.kinference:inference-core:0.2.22")
api("io.kinference:inference-core:0.2.23")
}
}

val jsMain by getting {
dependencies {
api("io.kinference:inference-tfjs:0.2.22")
api("io.kinference:inference-tfjs:0.2.23")
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask

group = "io.kinference"
version = "0.2.22-kotlin18"
version = "0.2.23-kotlin18"

plugins {
alias(libs.plugins.kotlin.multiplatform) apply false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ fun KotlinJvmTarget.configureBenchmarkTests() {
group = "verification"

maxHeapSize = "4G"
systemProperty("kotlinx.coroutines.debug", "off")

useJUnitPlatform()

Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ okio = "3.4.0"
onnxruntime = "1.17.0.patched-1"
slf4j = "2.0.9"
wire = "4.8.1"
fastutil = "8.5.14"

primitives = "0.1.26-kotlin18"

Expand Down Expand Up @@ -38,3 +39,4 @@ onnxruntime-gpu = { module = "com.microsoft.onnxruntime:onnxruntime_gpu", versio
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }
wire-runtime = { module = "com.squareup.wire:wire-runtime", version.ref = "wire" }
fastutil-core = { module = "it.unimi.dsi:fastutil-core", version.ref = "fastutil" }
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,19 @@ import io.kinference.core.optimizer.rules.OptimizerRuleSet
import io.kinference.data.ONNXData
import io.kinference.data.ONNXDataType
import io.kinference.model.IrOptimizableEngine
import io.kinference.ndarray.arrays.memory.MemoryLimiter
import io.kinference.ndarray.arrays.memory.MemoryLimiters
import io.kinference.optimizer.GraphOptimizer
import io.kinference.optimizer.OptimizerRule
import io.kinference.protobuf.*
import io.kinference.protobuf.message.*
import io.kinference.utils.CommonDataLoader
import io.kinference.utils.PlatformUtils
import io.kinference.utils.PredictionConfig
import io.kinference.utils.PredictionConfigs
import okio.Buffer
import okio.Path
import okio.Path.Companion.toPath

typealias KIONNXData<T> = ONNXData<T, CoreBackend>

// Define an interface for allocation control marking output
internal interface KIONNXDataArraysReleaser {
fun markOutput()
}

internal fun <T> KIONNXData<T>.markOutput() {
if (this is KIONNXDataArraysReleaser)
this.markOutput()
}

object CoreBackend : BackendInfo(name = "KInference Core CPU Backend")

/**
Expand All @@ -51,37 +40,37 @@ object KIEngine : IrOptimizableEngine<KIONNXData<*>> {

fun protoReader(bytes: ByteArray) = ProtobufReader(Buffer().write(bytes), KI_READER_CONFIG)

suspend fun loadModel(bytes: ByteArray, optimize: Boolean, memoryLimiter: MemoryLimiter, parallelismLimit: Int): KIModel {
suspend fun loadModel(bytes: ByteArray, optimize: Boolean, predictionConfig: PredictionConfig): KIModel {
val rules = if (optimize) OptimizerRuleSet.DEFAULT_OPT_RULES else emptyList()
return loadModel(bytes, rules, memoryLimiter, parallelismLimit)
return loadModel(bytes, rules, predictionConfig)
}

override suspend fun loadModel(bytes: ByteArray, optimize: Boolean): KIModel {
return loadModel(bytes, optimize, MemoryLimiters.NoAllocator, PlatformUtils.cores)
return loadModel(bytes, optimize, PredictionConfigs.NoAllocator)
}

override suspend fun loadModel(bytes: ByteArray, rules: List<OptimizerRule<KIONNXData<*>>>): KIModel = loadModel(bytes, rules, MemoryLimiters.NoAllocator, PlatformUtils.cores)
override suspend fun loadModel(bytes: ByteArray, rules: List<OptimizerRule<KIONNXData<*>>>): KIModel = loadModel(bytes, rules, PredictionConfigs.NoAllocator)

suspend fun loadModel(bytes: ByteArray, rules: List<OptimizerRule<KIONNXData<*>>>, memoryLimiter: MemoryLimiter, parallelismLimit: Int): KIModel {
suspend fun loadModel(bytes: ByteArray, rules: List<OptimizerRule<KIONNXData<*>>>, predictionConfig: PredictionConfig): KIModel {
val modelScheme = ModelProto.decode(protoReader(bytes))
val model = KIModel(modelScheme, memoryLimiter)
val model = KIModel(modelScheme, predictionConfig)

return if (rules.isNotEmpty()) {
val newGraph = GraphOptimizer(model.graph).run(rules) as KIGraph
KIModel(model.id, model.name, model.opSet, newGraph, memoryLimiter, parallelismLimit)
KIModel(model.id, model.name, model.opSet, newGraph, predictionConfig)
} else {
model
}
}

override suspend fun loadModel(bytes: ByteArray): KIModel = loadModel(bytes, optimize = true)

suspend fun loadModel(path: Path, optimize: Boolean, memoryLimiter: MemoryLimiter, parallelismLimit: Int): KIModel {
return loadModel(CommonDataLoader.bytes(path), optimize, memoryLimiter, parallelismLimit)
suspend fun loadModel(path: Path, optimize: Boolean, predictionConfig: PredictionConfig): KIModel {
return loadModel(CommonDataLoader.bytes(path), optimize, predictionConfig)
}

override suspend fun loadModel(path: Path, optimize: Boolean): KIModel {
return loadModel(path, optimize, MemoryLimiters.NoAllocator, PlatformUtils.cores)
return loadModel(path, optimize, PredictionConfigs.NoAllocator)
}

override suspend fun loadModel(path: Path): KIModel = loadModel(path, optimize = true)
Expand All @@ -90,12 +79,12 @@ object KIEngine : IrOptimizableEngine<KIONNXData<*>> {
return loadModel(CommonDataLoader.bytes(path), rules)
}

suspend fun loadModel(path: String, optimize: Boolean, memoryLimiter: MemoryLimiter, parallelismLimit: Int): KIModel {
return loadModel(CommonDataLoader.bytes(path.toPath()), optimize, memoryLimiter, parallelismLimit)
suspend fun loadModel(path: String, optimize: Boolean, predictionConfig: PredictionConfig): KIModel {
return loadModel(CommonDataLoader.bytes(path.toPath()), optimize, predictionConfig)
}

override suspend fun loadModel(path: String, optimize: Boolean): KIModel {
return loadModel(path, optimize, MemoryLimiters.NoAllocator, PlatformUtils.cores)
return loadModel(path, optimize, PredictionConfigs.NoAllocator)
}

override suspend fun loadModel(path: String): KIModel = loadModel(path, optimize = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import io.kinference.protobuf.message.TensorProto
import io.kinference.types.ValueInfo
import io.kinference.types.ValueTypeInfo

class KIONNXMap(name: String?, data: Map<Any, KIONNXData<*>>, val info: ValueTypeInfo.MapTypeInfo) : ONNXMap<Map<Any, KIONNXData<*>>, CoreBackend>(name, data), KIONNXDataArraysReleaser {
class KIONNXMap(name: String?, data: Map<Any, KIONNXData<*>>, val info: ValueTypeInfo.MapTypeInfo) : ONNXMap<Map<Any, KIONNXData<*>>, CoreBackend>(name, data) {
constructor(data: Map<Any, KIONNXData<*>>, info: ValueInfo) : this(info.name, data, info.typeInfo as ValueTypeInfo.MapTypeInfo)

override val backend = CoreBackend
Expand All @@ -26,10 +26,6 @@ class KIONNXMap(name: String?, data: Map<Any, KIONNXData<*>>, val info: ValueTyp

override fun rename(name: String): KIONNXMap = KIONNXMap(name, data, info)

override fun markOutput() {
data.values.forEach { it.markOutput() }
}

override suspend fun clone(newName: String?): KIONNXMap {
val newMap = HashMap<Any, KIONNXData<*>>(data.size)
for ((key, value) in data.entries) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import io.kinference.data.ONNXSequence
import io.kinference.protobuf.message.SequenceProto
import io.kinference.types.*

class KIONNXSequence(name: String?, data: List<KIONNXData<*>>, val info: ValueTypeInfo.SequenceTypeInfo) : ONNXSequence<List<KIONNXData<*>>, CoreBackend>(name, data), KIONNXDataArraysReleaser {
class KIONNXSequence(name: String?, data: List<KIONNXData<*>>, val info: ValueTypeInfo.SequenceTypeInfo) : ONNXSequence<List<KIONNXData<*>>, CoreBackend>(name, data) {
constructor(name: String?, info: ValueTypeInfo.SequenceTypeInfo, size: Int, init: (Int) -> KIONNXData<*>) : this(name, List(size, init), info)
constructor(data: List<KIONNXData<*>>, info: ValueInfo) : this(info.name, data, info.typeInfo as ValueTypeInfo.SequenceTypeInfo)

Expand All @@ -23,10 +23,6 @@ class KIONNXSequence(name: String?, data: List<KIONNXData<*>>, val info: ValueTy

override fun rename(name: String): KIONNXSequence = KIONNXSequence(name, data, info)

override fun markOutput() {
data.forEach { it.markOutput() }
}

val length: Int = data.size

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.kinference.core.data.tensor

import io.kinference.core.CoreBackend
import io.kinference.core.KIONNXDataArraysReleaser
import io.kinference.core.*
import io.kinference.data.ONNXTensor
import io.kinference.ndarray.arrays.*
import io.kinference.ndarray.arrays.memory.contexts.ManualAllocatorContext
import io.kinference.ndarray.arrays.tiled.*
import io.kinference.protobuf.FLOAT_TENSOR_TYPES
import io.kinference.protobuf.message.TensorProto
Expand All @@ -13,22 +13,18 @@ import io.kinference.types.ValueTypeInfo

//TODO: support segments
//TODO: support external data
class KITensor(name: String?, override val data: NDArrayCore, val info: ValueTypeInfo.TensorTypeInfo) : ONNXTensor<NDArrayCore, CoreBackend>(name, data), KIONNXDataArraysReleaser {
class KITensor(name: String?, override val data: NDArrayCore, val info: ValueTypeInfo.TensorTypeInfo, private var context: ManualAllocatorContext? = null) : ONNXTensor<NDArrayCore, CoreBackend>(name, data) {
constructor(data: NDArrayCore, info: ValueInfo) : this(info.name, data, info.typeInfo as ValueTypeInfo.TensorTypeInfo)

override suspend fun close() {
context?.returnNDArray(data)
data.close()
}

override suspend fun clone(newName: String?): KITensor {
return KITensor(newName, data.clone(), info)
}

override fun markOutput() {
if (this.data is MemoryControlledArray)
data.markOutput()
}

suspend operator fun minus(other: KITensor): KITensor {
require(this.data is NumberNDArrayCore && other.data is NumberNDArrayCore)
return (this.data - other.data).asTensor()
Expand All @@ -47,7 +43,7 @@ class KITensor(name: String?, override val data: NDArrayCore, val info: ValueTyp
override val backend = CoreBackend

override fun rename(name: String): KITensor {
return KITensor(name, data, info)
return KITensor(name, data, info, context)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package io.kinference.core.data.tensor

import io.kinference.ndarray.arrays.*
import io.kinference.ndarray.arrays.memory.contexts.ManualAllocatorContext
import io.kinference.ndarray.extensions.concat
import io.kinference.ndarray.extensions.splitWithAxis
import io.kinference.primitives.types.DataType
import io.kinference.protobuf.resolveProtoDataType
import io.kinference.types.TensorShape
import io.kinference.types.ValueTypeInfo

fun NDArrayCore.asTensor(name: String? = null) = KITensor(name, this, ValueTypeInfo.TensorTypeInfo(TensorShape(this.shape), type.resolveProtoDataType()))
fun NDArrayCore.asTensor(name: String? = null, context: ManualAllocatorContext? = null) = KITensor(name, this, ValueTypeInfo.TensorTypeInfo(TensorShape(this.shape), type.resolveProtoDataType()), context)

internal fun <T : NDArray> T.asTensor(name: String? = null) = (this as NDArrayCore).asTensor(name)
internal fun <T : NDArray> T.asTensor(name: String? = null, context: ManualAllocatorContext? = null) = (this as NDArrayCore).asTensor(name, context)

internal fun <T : NDArray> Collection<T>.asONNXTensors(names: List<String>): List<KITensor> {
return this.zip(names).map { (data, name) -> data.asTensor(name) }
Expand Down
Loading

0 comments on commit 5b44daf

Please sign in to comment.