Skip to content

Latest commit

 

History

History
197 lines (131 loc) · 6.54 KB

FAQ.md

File metadata and controls

197 lines (131 loc) · 6.54 KB

FAQ

Frequently asked questions about Multik — setup, engines, platform support, common pitfalls, and differences from NumPy. Common questions about setup, engines, platform support, and usage. FAQ — frequently asked questions about Multik.

Setup and installation

I get "The map of engines is empty" or "Fail to find engine". What's wrong?

You need to add an engine dependency alongside multik-core. The core module only provides types and interfaces — it does not include an implementation.

Add one of the following:

// Recommended — auto-selects the best engine per platform
implementation("org.jetbrains.kotlinx:multik-default:$multikVersion")

// Pure Kotlin only (all platforms, no native dependencies)
implementation("org.jetbrains.kotlinx:multik-kotlin:$multikVersion")

Make sure all Multik artifact versions match.

The multik-openblas JAR is very large (~115 MB). Can I reduce it?

The JVM artifact bundles native libraries for all desktop platforms (Linux x64, macOS x64/arm64, Windows x64) in a single JAR. Platform-specific artifacts are not yet available.

Workaround: If size is critical, use multik-kotlin instead — it is much smaller and has no native dependencies.

I get GLIBC_2.35 not found on Linux

The pre-built native library in multik-openblas requires glibc 2.35+. Older distributions (e.g., Ubuntu 20.04) do not have it.

Solutions:

  • Upgrade to Ubuntu 22.04+ or equivalent.
  • Use multik-kotlin instead.
  • Build the native library from source against your system's glibc.

Engines

How do I select or switch between engines?

multik-default auto-detects and loads the best engine. You can switch at runtime:

mk.setEngine(KEEngineType)     // Pure Kotlin engine
mk.setEngine(NativeEngineType) // OpenBLAS native engine

Different engines may produce slightly different results for decompositions. For example, linalg.qr returns a reduced decomposition with the native engine but a full decomposition with the Kotlin engine. {style="note"}

Why is the first Multik call slow?

The native engine (OpenBLAS) is lazily loaded on first use — the library is extracted from the JAR and loaded via JNI. Subsequent calls are fast.

Workarounds:

  • Perform a small warm-up call during application startup.
  • Use multik-kotlin if startup latency matters more than computation speed.

Platform support

Does Multik work on Android?

Yes. Every Multik module publishes an Android artifact (AAR), so add the same dependencies as on other targets.

  • Android artifacts require minSdk 28.
  • The native engine ships a library for arm64-v8a only. On other ABIs (x86_64 emulators, armeabi-v7a), multik-default uses the Kotlin engine instead.
  • Depend on multik-default or multik-openblas, not on multik-openblas-jvm. The -jvm artifact is built for the desktop JVM: it bundles desktop .so files that fail Android builds with "libmultik_jni-linuxX64.so is not an ABI".

Does Multik work on Kotlin/Native, JS, and WASM?

multik-kotlin supports JVM, Android, JS, Native, and WASM targets.

multik-openblas is available only on JVM, Android, and desktop Native (Linux x64, macOS arm64, Windows x64). It is not available on iOS, JS, or WASM.

WASM support is experimental. Some operations (e.g., type casting in the multidimensional case) may throw exceptions. {style="warning"}

Common pitfalls

Reshaping a sliced array returns a view, not a copy

reshape returns a view whenever the new shape can be addressed with strides over the existing data — which includes most slices. Writing to the result writes through to the original array.

Fix: Call .deepCopy() first if you need a standalone array:

val slice = array[0..1, 0..1]
val reshaped = slice.deepCopy().reshape(1, 4)  // detached from `array`

Mixing numeric types causes a runtime error

Multik does not support the generic Number type as an element type. When you mix types like 1.0 (Double) and 2 (Int) in mk[1.0, 2], the compiler infers Number, which compiles but fails at runtime.

Fix: Ensure all elements use the same type:

mk.ndarray(mk[1.0, 2.0])   // all Double — correct
mk.ndarray(mk[1, 2])        // all Int — correct
// mk.ndarray(mk[1.0, 2])   // Number — runtime error!

dot on sliced views can return incorrect results

Computing dot on a row extracted from a 2D array (which is a view) may produce wrong results, especially with the native engine.

Fix: Copy the slice first:

val row = matrix[0].copy()   // explicit copy
val result = row dot vector   // now correct

Integer division truncates

mk.ndarray(mk[5]) / 2 yields [2], not [2.5]. Use Double or Float arrays for fractional results.

NumPy comparison

Does Multik support broadcasting?

No. Multik does not support NumPy-style broadcasting. Array-array operations require both operands to have the same shape.

Workaround: Use .map or create a same-shaped array of the scalar value.

Does Multik support boolean masks or where?

No. Element-wise comparisons that return boolean arrays (like array == 0), boolean indexing (array[mask]), and np.where(condition, x, y) are not yet supported.

Workaround: Use filter, mapIndexed, or manual iteration:

val a = mk.ndarray(mk[1, 2, 3, 4, 5])
a.filter { it > 3 }   // [4, 5]

How do I do matrix multiplication?

Use mk.linalg.dot(a, b) or the infix syntax a dot b. This handles matrix-matrix, matrix-vector, and vector-vector products. See dot for details.

* is element-wise multiplication, not matrix multiplication. {style="warning"}

I/O

Can I read .npy files?

.npy format is supported on JVM and Android. It is not available on Native, JS, or WASM targets.

Can I read CSV files with complex numbers?

CSV reading exists but has known issues when parsing complex numbers formatted by NumPy. As a workaround, parse the file manually and construct the complex array in code.