Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ public class sk/ainet/exec/tensor/ops/DefaultCpuOpsBase : sk/ainet/lang/tensor/o
public fun abs (Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun add (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
public fun addScalar (Lsk/ainet/lang/tensor/Tensor;Ljava/lang/Number;)Lsk/ainet/lang/tensor/Tensor;
public fun argMax (Lsk/ainet/lang/tensor/Tensor;I)Lsk/ainet/lang/tensor/Tensor;
public fun avgPool2d (Lsk/ainet/lang/tensor/Tensor;Lkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;Z)Lsk/ainet/lang/tensor/Tensor;
protected final fun broadcastShapes (Lsk/ainet/lang/tensor/Shape;Lsk/ainet/lang/tensor/Shape;)Lsk/ainet/lang/tensor/Shape;
protected final fun chooseQuantizedMatmulHeap (Lsk/ainet/lang/tensor/Tensor;Lsk/ainet/lang/tensor/Tensor;)Lsk/ainet/lang/tensor/Tensor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2050,6 +2050,46 @@ public open class DefaultCpuOpsBase(protected val dataFactory: TensorDataFactory
}
}

@TensorOp()
@InProgress("cpu", owner = "team:cpu", issue = "task-ops.md#op-argmax")
override fun <T : DType, V> argMax(tensor: Tensor<T, V>, dim: Int): Tensor<T, V> {
val rank = tensor.rank
require(rank >= 1) { "argMax: input must have rank >= 1" }
val nd = if (dim < 0) dim + rank else dim
require(nd in 0 until rank) { "argMax: dim $dim out of range for rank $rank" }
val inDims = tensor.shape.dimensions
// Reduced (dim removed) shape; scalar -> Shape(1) to match VoidTensorOps.
val reduced = IntArray(rank - 1)
run { var o = 0; for (i in 0 until rank) if (i != nd) reduced[o++] = inDims[i] }
val outShape = if (reduced.isEmpty()) Shape(1) else Shape(reduced)
val outCount = reduced.fold(1) { a, b -> a * b }
val indices = IntArray(outCount)
val outIdx = IntArray(reduced.size)
for (flat in 0 until outCount) {
val inIdx = IntArray(rank)
run { var o = 0; for (i in 0 until rank) if (i != nd) inIdx[i] = outIdx[o++] }
var bestK = 0
var bestV = Float.NEGATIVE_INFINITY
for (k in 0 until inDims[nd]) {
inIdx[nd] = k
val v = (tensor.data.get(*inIdx) as Number).toFloat()
if (v > bestV) { bestV = v; bestK = k } // strict > keeps the LOWEST index on ties
}
indices[flat] = bestK
var d = reduced.size - 1
while (d >= 0) { outIdx[d]++; if (outIdx[d] < reduced[d]) break; outIdx[d] = 0; d-- }
}
// Eager result: store the indices as index-valued floats in the INPUT dtype so the tensor is
// a consistent Tensor<T,V> readable on every target (an Int32 payload inside a <FP32,Float>
// tensor throws ClassCastException on Kotlin/Native + Wasm). The traced/compiled form is a
// real i32 tensor — see VoidTensorOps.argMax + ArgMaxOperationsConverter (emits stablehlo i32).
val floats = FloatArray(outCount) { indices[it].toFloat() }
@Suppress("UNCHECKED_CAST")
val outData = dataFactory.fromFloatArray<T, Float>(outShape, tensor.dtype, floats)
as sk.ainet.lang.tensor.data.TensorData<T, V>
return CpuTensor(outData, this, tensor.dtype, GradState(requiresGrad = false))
}

@TensorOp()
@InProgress("cpu", owner = "team:cpu", issue = "task-ops.md#op-mean")
override fun <T : DType, V> mean(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package sk.ainet.sk.ainet.exec.tensor.ops

import kotlin.test.Test
import kotlin.test.assertEquals
import sk.ainet.context.DirectCpuExecutionContext
import sk.ainet.context.data
import sk.ainet.lang.tensor.Shape
import sk.ainet.lang.tensor.Tensor
import sk.ainet.lang.tensor.dsl.tensor
import sk.ainet.lang.types.FP32

class DefaultCpuOpsArgMaxTest {
private val ctx = DirectCpuExecutionContext()
private val ops get() = ctx.ops

// Eager argMax returns index-valued floats in the input dtype (portable across JVM/native/wasm);
// read them back as ints.
private fun idx(t: Tensor<FP32, Float>, vararg i: Int): Int = (t.data.get(*i) as Number).toInt()

@Test
fun argmax_last_dim_returns_indices_drops_dim_and_is_int32() {
data(ctx) { _ ->
// [2,3]: row0 max at col2 (7), row1 max at col0 (9)
val v = floatArrayOf(1f, 3f, 7f, 9f, 2f, 5f)
val t = tensor<FP32, Float> { shape(2, 3) { init { v[it[0] * 3 + it[1]] } } }
val r = ops.argMax(t, dim = -1)
assertEquals(Shape(2), r.shape)
assertEquals<Any>(FP32::class, r.dtype) // eager result is the input dtype (index-valued floats)
assertEquals(2, idx(r, 0))
assertEquals(0, idx(r, 1))
}
}

@Test
fun argmax_ties_break_to_lowest_index() {
data(ctx) { _ ->
val v = floatArrayOf(5f, 5f, 2f, 5f) // maxima at indices 0,1,3 -> lowest is 0
val t = tensor<FP32, Float> { shape(1, 4) { init { v[it[1]] } } }
val r = ops.argMax(t, dim = 1)
assertEquals(Shape(1), r.shape)
assertEquals(0, idx(r, 0))
}
}

@Test
fun argmax_middle_dim() {
data(ctx) { _ ->
// [2,3,1]: reduce dim 1 -> [2,1]; per (row, last) the max over the 3 middle entries
val v = floatArrayOf(/*r0*/ 4f, 9f, 1f, /*r1*/ 2f, 0f, 8f)
val t = tensor<FP32, Float> { shape(2, 3, 1) { init { v[it[0] * 3 + it[1]] } } }
val r = ops.argMax(t, dim = 1)
assertEquals(Shape(2, 1), r.shape)
assertEquals(1, idx(r, 0, 0)) // row0 max 9 at mid=1
assertEquals(2, idx(r, 1, 0)) // row1 max 8 at mid=2
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ internal class RecordingTensorOpsDecorator(private val base: TensorOps) : Tensor
override fun <T : DType, V> sum(tensor: Tensor<T, V>, dim: Int?): Tensor<T, V> = base.sum(tensor, dim)
override fun <T : DType, V> mean(tensor: Tensor<T, V>, dim: Int?): Tensor<T, V> = base.mean(tensor, dim)
override fun <T : DType, V> variance(tensor: Tensor<T, V>, dim: Int?): Tensor<T, V> = base.variance(tensor, dim)
override fun <T : DType, V> argMax(tensor: Tensor<T, V>, dim: Int): Tensor<T, V> = base.argMax(tensor, dim)
override fun <T : DType, V> sqrt(tensor: Tensor<T, V>): Tensor<T, V> = base.sqrt(tensor)
override fun <T : DType, V> log(tensor: Tensor<T, V>): Tensor<T, V> = base.log(tensor)
override fun <T : DType, V> log2(tensor: Tensor<T, V>): Tensor<T, V> = base.log2(tensor)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
public final class sk/ainet/compile/target/FusedOpAllowList : sk/ainet/compile/target/OpGranularityPolicy {
public fun <init> (Ljava/lang/String;Ljava/util/Set;)V
public fun getTarget ()Ljava/lang/String;
public fun keepFused (Ljava/lang/String;)Z
}

public abstract interface class sk/ainet/compile/target/OpGranularityPolicy {
public abstract fun getTarget ()Ljava/lang/String;
public abstract fun keepFused (Ljava/lang/String;)Z
}

public abstract interface class sk/ainet/lang/graph/ComputeGraph {
public abstract fun addEdge (Lsk/ainet/lang/graph/GraphEdge;)Lsk/ainet/lang/graph/GraphEdge;
public abstract fun addNode (Lsk/ainet/lang/graph/GraphNode;)Lsk/ainet/lang/graph/GraphNode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ private class TestTensorOps : TensorOps {
override fun <T : DType, V> sum(tensor: Tensor<T, V>, dim: Int?): Tensor<T, V> = tensor
override fun <T : DType, V> mean(tensor: Tensor<T, V>, dim: Int?): Tensor<T, V> = tensor
override fun <T : DType, V> variance(tensor: Tensor<T, V>, dim: Int?): Tensor<T, V> = tensor
override fun <T : DType, V> argMax(tensor: Tensor<T, V>, dim: Int): Tensor<T, V> = tensor
override fun <T : DType, V> sqrt(tensor: Tensor<T, V>): Tensor<T, V> = tensor
override fun <T : DType, V> pow(a: Tensor<T, V>, b: Tensor<T, V>): Tensor<T, V> = a
override fun <T : DType, V> powScalar(a: Tensor<T, V>, n: Number): Tensor<T, V> = a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ public final class sk/ainet/compile/hlo/ConversionContext {
public fun <init> (Lsk/ainet/compile/hlo/TypeMapper;)V
public fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;)V
public fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;)V
public synthetic fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;)V
public fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;)V
public synthetic fun <init> (Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun clear ()V
public final fun emitComment (Ljava/lang/String;)V
public final fun emitEncodingAnnotation (Ljava/lang/String;ILsk/ainet/lang/tensor/ops/TensorSpec;)V
Expand All @@ -54,9 +56,11 @@ public final class sk/ainet/compile/hlo/ConversionContext {
public final fun emitOperation (Ljava/lang/String;)V
public final fun getContent ()Ljava/lang/String;
public final fun getExternalParameters ()Ljava/util/List;
public final fun getGranularity ()Lsk/ainet/compile/target/OpGranularityPolicy;
public final fun getInputNodes (Lsk/ainet/lang/graph/GraphNode;)Ljava/util/List;
public final fun getMaterializationPolicy ()Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;
public final fun getModuleDeclarations ()Ljava/lang/String;
public final fun getTarget ()Ljava/lang/String;
public final fun getTypeMapper ()Lsk/ainet/compile/hlo/TypeMapper;
public final fun getValueName (Ljava/lang/String;)Ljava/lang/String;
public final fun getValueName (Ljava/lang/String;I)Ljava/lang/String;
Expand Down Expand Up @@ -115,10 +119,10 @@ public final class sk/ainet/compile/hlo/ConversionResult$Unsupported : sk/ainet/
}

public final class sk/ainet/compile/hlo/Dag2hloKt {
public static final fun toStableHlo (Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;)Lsk/ainet/compile/hlo/StableHloModule;
public static final fun toStableHlo (Lsk/ainet/lang/graph/ResolvedComputeGraph;Ljava/lang/String;Z)Lsk/ainet/compile/hlo/StableHloModule;
public static synthetic fun toStableHlo$default (Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloModule;
public static synthetic fun toStableHlo$default (Lsk/ainet/lang/graph/ResolvedComputeGraph;Ljava/lang/String;ZILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloModule;
public static final fun toStableHlo (Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;)Lsk/ainet/compile/hlo/StableHloModule;
public static final fun toStableHlo (Lsk/ainet/lang/graph/ResolvedComputeGraph;Ljava/lang/String;ZLjava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;)Lsk/ainet/compile/hlo/StableHloModule;
public static synthetic fun toStableHlo$default (Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloModule;
public static synthetic fun toStableHlo$default (Lsk/ainet/lang/graph/ResolvedComputeGraph;Ljava/lang/String;ZLjava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloModule;
public static final fun toStableHloLegacy (Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;)Lsk/ainet/compile/hlo/StableHloModule;
public static synthetic fun toStableHloLegacy$default (Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloModule;
}
Expand Down Expand Up @@ -180,7 +184,9 @@ public final class sk/ainet/compile/hlo/StableHloConverter {
public fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;)V
public fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;)V
public fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;)V
public synthetic fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;)V
public fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;)V
public synthetic fun <init> (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun convert (Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;)Lsk/ainet/compile/hlo/StableHloModule;
public static synthetic fun convert$default (Lsk/ainet/compile/hlo/StableHloConverter;Lsk/ainet/lang/graph/ComputeGraph;Ljava/lang/String;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloModule;
public final fun convertWithOptimization (Lsk/ainet/lang/graph/ComputeGraph;Lsk/ainet/compile/hlo/StableHloOptimizer;)Lsk/ainet/compile/hlo/StableHloModule;
Expand All @@ -190,7 +196,9 @@ public final class sk/ainet/compile/hlo/StableHloConverterFactory {
public static final field INSTANCE Lsk/ainet/compile/hlo/StableHloConverterFactory;
public static final fun createBasic ()Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createBasic (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createBasic$default (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createBasic (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createBasic (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;)Lsk/ainet/compile/hlo/StableHloConverter;
public static synthetic fun createBasic$default (Lsk/ainet/compile/hlo/ConstantMaterializationPolicy;Ljava/lang/String;Lsk/ainet/compile/target/OpGranularityPolicy;ILjava/lang/Object;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createCustom (Lsk/ainet/compile/hlo/StableHloOperationRegistry;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createCustom (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;)Lsk/ainet/compile/hlo/StableHloConverter;
public static final fun createCustom (Lsk/ainet/compile/hlo/StableHloOperationRegistry;Lsk/ainet/compile/hlo/TypeMapper;Lsk/ainet/compile/hlo/MlirValidator;)Lsk/ainet/compile/hlo/StableHloConverter;
Expand Down Expand Up @@ -315,6 +323,7 @@ public final class sk/ainet/compile/hlo/TypeMapper {
public final fun mapDType (Ljava/lang/String;)Ljava/lang/String;
public final fun mapFunctionSignature (Ljava/util/List;Ljava/util/List;)Ljava/lang/String;
public final fun mapTensorType (Lsk/ainet/lang/tensor/ops/TensorSpec;)Ljava/lang/String;
public final fun negInfBits (Ljava/lang/String;)Ljava/lang/String;
}

public final class sk/ainet/compile/hlo/converters/ActivationOperationsConverter : sk/ainet/compile/hlo/StableHloOperationConverter {
Expand All @@ -323,6 +332,12 @@ public final class sk/ainet/compile/hlo/converters/ActivationOperationsConverter
public fun getSupportedOperations ()Ljava/util/Set;
}

public final class sk/ainet/compile/hlo/converters/ArgMaxOperationsConverter : sk/ainet/compile/hlo/StableHloOperationConverter {
public fun <init> ()V
public fun convert (Lsk/ainet/lang/graph/GraphNode;Ljava/util/List;Lsk/ainet/compile/hlo/ConversionContext;)Lsk/ainet/compile/hlo/ConversionResult;
public fun getSupportedOperations ()Ljava/util/Set;
}

public final class sk/ainet/compile/hlo/converters/AttentionOperationsConverter : sk/ainet/compile/hlo/StableHloOperationConverter {
public fun <init> ()V
public fun convert (Lsk/ainet/lang/graph/GraphNode;Ljava/util/List;Lsk/ainet/compile/hlo/ConversionContext;)Lsk/ainet/compile/hlo/ConversionResult;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sk.ainet.compile.hlo

import sk.ainet.compile.hlo.converters.ActivationOperationsConverter
import sk.ainet.compile.hlo.converters.ArgMaxOperationsConverter
import sk.ainet.compile.hlo.converters.AttentionOperationsConverter
import sk.ainet.compile.hlo.converters.ConstantOperationsConverter
import sk.ainet.compile.hlo.converters.GatherOperationsConverter
Expand Down Expand Up @@ -57,6 +58,8 @@ public object StableHloConverterFactory {

// Register reduction operations converter
registry.register(ReductionOperationsConverter())
// argMax: logits -> index, lowered to reduce-max + broadcast + compare + iota + select + reduce-min
registry.register(ArgMaxOperationsConverter())

// Register elementwise unary math converter (sqrt, exp, log, abs, …).
// Must be present so downstream consumers don't cascade-fail with
Expand Down Expand Up @@ -114,6 +117,8 @@ public object StableHloConverterFactory {

// Register reduction operations converter
registry.register(ReductionOperationsConverter())
// argMax: logits -> index, lowered to reduce-max + broadcast + compare + iota + select + reduce-min
registry.register(ArgMaxOperationsConverter())

// Register elementwise unary math converter (sqrt, exp, log, abs, …).
// Must be present so downstream consumers don't cascade-fail with
Expand Down Expand Up @@ -157,6 +162,8 @@ public object StableHloConverterFactory {
registry.register(ActivationOperationsConverter())
registry.register(ShapeOperationsConverter())
registry.register(ReductionOperationsConverter())
// argMax: logits -> index, lowered to reduce-max + broadcast + compare + iota + select + reduce-min
registry.register(ArgMaxOperationsConverter())
registry.register(UnaryMathConverter())
registry.register(ScalarOperationsConverter())
registry.register(ConstantOperationsConverter())
Expand Down
Loading
Loading