Skip to content

Commit ee0e405

Browse files
committed
refactor(cpu): route Ling stateful ops through mllm abstractions
1 parent f598969 commit ee0e405

30 files changed

Lines changed: 892 additions & 47 deletions

examples/ling3/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ The runner emits `LING3_RUN_START`, generated token IDs, and
4141
runtime result; device evidence must retain the converted model SHA256 and
4242
the runner/library identities together.
4343

44-
For a longer deterministic correctness demo, use the checked-in prompt and a
45-
64-token generation limit:
44+
For a longer correctness demo, pass the prompt directly and use a 64-token
45+
generation limit:
4646

4747
```bash
4848
./mllm-ling3-runner \
4949
--model_path /path/to/Ling-3.0-tiny.mllm \
5050
--tokenizer_path /path/to/Ling-3.0-tiny/tokenizer.json \
5151
--config_path config_tiny_w4a32_kai.json \
52-
--prompt_file demo_prompt_v1.txt --disable_thinking \
52+
--prompt '请用中文详细介绍 Ling-3.0-tiny 的混合注意力架构,并解释 KDA、MLA 和 MoE 各自的作用。' --disable_thinking \
5353
--max_new_tokens 64 --print_token_ids
5454
```
5555

examples/ling3/demo_prompt_v1.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

mllm/backends/cpu/CPUBackend.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "mllm/backends/cpu/ops/AvgPool1dOp.hpp"
1010
#include "mllm/backends/cpu/ops/CastTypeOp.hpp"
1111
#include "mllm/backends/cpu/ops/CausalMaskOp.hpp"
12+
#include "mllm/backends/cpu/ops/CausalDepthwiseConv1DOp.hpp"
1213
#include "mllm/backends/cpu/ops/CloneOp.hpp"
1314
#include "mllm/backends/cpu/ops/CmpOp.hpp"
1415
#include "mllm/backends/cpu/ops/ConcatOp.hpp"
@@ -36,6 +37,7 @@
3637
#include "mllm/backends/cpu/ops/ISTFTOp.hpp"
3738
#include "mllm/backends/cpu/ops/IndexOp.hpp"
3839
#include "mllm/backends/cpu/ops/KVCacheOp.hpp"
40+
#include "mllm/backends/cpu/ops/KimiDeltaAttentionOp.hpp"
3941
#include "mllm/backends/cpu/ops/LayerNormOp.hpp"
4042
#include "mllm/backends/cpu/ops/LinearOp.hpp"
4143
#include "mllm/backends/cpu/ops/MatMulOp.hpp"
@@ -83,7 +85,7 @@ CPUBackend::CPUBackend() : Backend(kCPU, createCPUAllocator()) {
8385
CPUConv2DOpFactory, CPULayerNorm2DOpFactory, CPUInterpolateOpFactory, CPUPadOpFactory, CPUMaskedScatterOpFactory,
8486
CPUArgsortOpFactory, CPUCloneOpFactory, CPUAvgPool1dOpFactory, CPUFlashAttention2SwaSinkOpFactory,
8587
CPURadixAttnRelaxOpFactory, CPURadixAttnSwaSinkOpFactory, CPUEqualOpFactory, CPUWhereOpFactory,
86-
CPUGatherOpFactory>();
88+
CPUGatherOpFactory, CPUKimiDeltaAttentionOpFactory, CPUCausalDepthwiseConv1DOpFactory>();
8789
}
8890

8991
CPUBackend::~CPUBackend() {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) MLLM Team.
2+
// Licensed under the MIT License.
3+
4+
#include "mllm/backends/cpu/ops/CausalDepthwiseConv1DOp.hpp"
5+
6+
#include <cstring>
7+
#include <stdexcept>
8+
9+
#include "mllm/backends/cpu/kernels/common/gdn/gated_delta_net.hpp"
10+
11+
namespace mllm::cpu {
12+
13+
CPUCausalDepthwiseConv1DOp::CPUCausalDepthwiseConv1DOp(const aops::CausalDepthwiseConv1DOpOptions& options)
14+
: aops::CausalDepthwiseConv1DOp(options) {}
15+
16+
void CPUCausalDepthwiseConv1DOp::forward(const std::vector<Tensor>& inputs, std::vector<Tensor>& outputs) {
17+
for (const auto& input : inputs) {
18+
if (!input.isContiguous()) { throw std::invalid_argument("CausalDepthwiseConv1D CPU inputs must be contiguous"); }
19+
}
20+
21+
const auto& input = inputs[0];
22+
const auto& weight = inputs[1];
23+
const auto& state = inputs[2];
24+
auto& output = outputs[0];
25+
auto& updated_state = outputs[1];
26+
if (!options_.state_inplace) { std::memcpy(updated_state.ptr<float>(), state.ptr<float>(), state.bytes()); }
27+
gdn::depthwiseCausalConvF32(input.ptr<float>(), weight.ptr<float>(), updated_state.ptr<float>(), output.ptr<float>(),
28+
input.shape()[0], input.shape()[1], input.shape()[2], weight.shape()[2]);
29+
}
30+
31+
} // namespace mllm::cpu
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) MLLM Team.
2+
// Licensed under the MIT License.
3+
4+
#pragma once
5+
6+
#include "mllm/core/aops/CausalDepthwiseConv1DOp.hpp"
7+
8+
namespace mllm::cpu {
9+
10+
class CPUCausalDepthwiseConv1DOp final : public aops::CausalDepthwiseConv1DOp {
11+
public:
12+
explicit CPUCausalDepthwiseConv1DOp(const aops::CausalDepthwiseConv1DOpOptions& options);
13+
14+
void forward(const std::vector<Tensor>& inputs, std::vector<Tensor>& outputs) override;
15+
};
16+
17+
class CPUCausalDepthwiseConv1DOpFactory
18+
: public TypedOpFactory<OpTypes::kCausalDepthwiseConv1D, aops::CausalDepthwiseConv1DOpOptions> {
19+
public:
20+
std::shared_ptr<BaseOp> createOpImpl(const aops::CausalDepthwiseConv1DOpOptions& options) override {
21+
return std::make_shared<CPUCausalDepthwiseConv1DOp>(options);
22+
}
23+
};
24+
25+
} // namespace mllm::cpu
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) MLLM Team.
2+
// Licensed under the MIT License.
3+
4+
#include "mllm/backends/cpu/ops/KimiDeltaAttentionOp.hpp"
5+
6+
#include <cstring>
7+
#include <stdexcept>
8+
9+
#include "mllm/backends/cpu/kernels/common/kda/kimi_delta_attention.hpp"
10+
11+
namespace mllm::cpu {
12+
13+
CPUKimiDeltaAttentionOp::CPUKimiDeltaAttentionOp(const aops::KimiDeltaAttentionOpOptions& options)
14+
: aops::KimiDeltaAttentionOp(options) {}
15+
16+
void CPUKimiDeltaAttentionOp::forward(const std::vector<Tensor>& inputs, std::vector<Tensor>& outputs) {
17+
for (const auto& input : inputs) {
18+
if (!input.isContiguous()) { throw std::invalid_argument("KimiDeltaAttention CPU inputs must be contiguous"); }
19+
}
20+
21+
const auto& q = inputs[0];
22+
auto& output = outputs[0];
23+
auto& updated_state = outputs[1];
24+
if (!options_.state_inplace) { std::memcpy(updated_state.ptr<float>(), inputs[7].ptr<float>(), inputs[7].bytes()); }
25+
kda::kimiDeltaAttentionF32(inputs[0].ptr<float>(), inputs[1].ptr<float>(), inputs[2].ptr<float>(), inputs[3].ptr<float>(),
26+
inputs[4].ptr<float>(), inputs[5].ptr<float>(), inputs[6].ptr<float>(), updated_state.ptr<float>(),
27+
output.ptr<float>(), q.shape()[0], q.shape()[1], q.shape()[2], q.shape()[3], options_.safe_gate,
28+
options_.lower_bound, options_.getThreads());
29+
}
30+
31+
} // namespace mllm::cpu
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) MLLM Team.
2+
// Licensed under the MIT License.
3+
4+
#pragma once
5+
6+
#include "mllm/core/aops/KimiDeltaAttentionOp.hpp"
7+
8+
namespace mllm::cpu {
9+
10+
class CPUKimiDeltaAttentionOp final : public aops::KimiDeltaAttentionOp {
11+
public:
12+
explicit CPUKimiDeltaAttentionOp(const aops::KimiDeltaAttentionOpOptions& options);
13+
14+
void forward(const std::vector<Tensor>& inputs, std::vector<Tensor>& outputs) override;
15+
};
16+
17+
class CPUKimiDeltaAttentionOpFactory : public TypedOpFactory<OpTypes::kKimiDeltaAttention, aops::KimiDeltaAttentionOpOptions> {
18+
public:
19+
std::shared_ptr<BaseOp> createOpImpl(const aops::KimiDeltaAttentionOpOptions& options) override {
20+
return std::make_shared<CPUKimiDeltaAttentionOp>(options);
21+
}
22+
};
23+
24+
} // namespace mllm::cpu

mllm/compile/ir/GeneratedRTTIKind.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Auto generated: 2026-01-09 07:46:43
1+
// Auto generated: 2026-08-13 00:11:43
22
// do not modify this file
33
#pragma once
44

@@ -51,6 +51,8 @@ enum NodeKind : uint32_t {
5151
RK_Op_LinalgIROp_MultimodalRoPEOp,
5252
RK_Op_LinalgIROp_VisionRoPEOp,
5353
RK_Op_LinalgIROp_QuickGELUOp,
54+
RK_Op_LinalgIROp_KimiDeltaAttentionOp,
55+
RK_Op_LinalgIROp_CausalDepthwiseConv1DOp,
5456
RK_Op_LinalgIROp_CopyOp,
5557
RK_Op_LinalgIROp_CloneOp,
5658
RK_Op_LinalgIROp_NegOp,

mllm/compile/ir/NodeRTTIClassOfImpl.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Auto generated: 2026-01-09 07:46:43
1+
// Auto generated: 2026-08-13 00:11:43
22
// do not modify this file
33
#pragma once
44
namespace mllm::ir {
@@ -123,6 +123,13 @@ struct NodeRTTIClassOfImpl {
123123
#define RTTI_RK_OP_LINALGIROP_QUICKGELUOP_IMPL(v) \
124124
return (v)->getKind() >= RK_Op_LinalgIROp_QuickGELUOp && (v)->getKind() <= RK_Op_LinalgIROp_QuickGELUOp
125125

126+
#define RTTI_RK_OP_LINALGIROP_KIMIDELTAATTENTIONOP_IMPL(v) \
127+
return (v)->getKind() >= RK_Op_LinalgIROp_KimiDeltaAttentionOp && (v)->getKind() <= RK_Op_LinalgIROp_KimiDeltaAttentionOp
128+
129+
#define RTTI_RK_OP_LINALGIROP_CAUSALDEPTHWISECONV1DOP_IMPL(v) \
130+
return (v)->getKind() >= RK_Op_LinalgIROp_CausalDepthwiseConv1DOp \
131+
&& (v)->getKind() <= RK_Op_LinalgIROp_CausalDepthwiseConv1DOp
132+
126133
#define RTTI_RK_OP_LINALGIROP_COPYOP_IMPL(v) \
127134
return (v)->getKind() >= RK_Op_LinalgIROp_CopyOp && (v)->getKind() <= RK_Op_LinalgIROp_CopyOp
128135

mllm/compile/ir/linalg/Op.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ LINALG_AOPS_DECL(OpTypes::kMultimodalRoPE, MultimodalRoPEOp);
8080
LINALG_AOPS_DECL(OpTypes::kVisionRoPE, VisionRoPEOp);
8181

8282
LINALG_AOPS_DECL(OpTypes::kQuickGELU, QuickGELUOp);
83+
LINALG_AOPS_DECL(OpTypes::kKimiDeltaAttention, KimiDeltaAttentionOp);
84+
LINALG_AOPS_DECL(OpTypes::kCausalDepthwiseConv1D, CausalDepthwiseConv1DOp);
8385

8486
LINALG_AOPS_DECL(OpTypes::kCopy, CopyOp);
8587
LINALG_AOPS_DECL(OpTypes::kClone, CloneOp);

0 commit comments

Comments
 (0)