[Feature]: key-padding lengths for scaledDotProductAttention — mask as op metadata, lengths-based lowering
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 18/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- kotlin
- Lĩnh vực
- compilers, machine-learning
Hướng nghiên cứu
Start from TensorOps.scaledDotProductAttention, then follow the mask handling in DefaultCpuOps.scaledDotProductAttention, RecordingExecution, and AttentionOperationsConverter, which the issue names. The issue depends on the not-yet-built LoweringSpec from #1342, so check that first. Done means the acceptance checklist holds: a padded batch matches unpadded single passes within 1e-5, and the dense mask path is unchanged.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
🧠 D: DEFINE — Problem & Opportunity
TensorOps.scaledDotProductAttention(query, key, value, mask, scale, causal) knows two mask forms: the causal flag and an opaque additive mask tensor [batch, 1, seqLen, kvLen]. There is no notion of a key-padding mask, so a batch of sequences with different lengths can only be attended by baking -1e30 into that dense tensor on the caller's side.
That works on the eager path and loses the structure everywhere else:
- the recorded graph (
RecordingExecution→ScaledDotProductAttentionOperation,parameters = { scale, causal }) sees a per-call constant of sizeb·Sq·Skper layer instead of "these keys are padding"; - the StableHLO converter (
AttentionOperationsConverter) can only broadcast and add it before the softmax; a fused attention kernel on a vendor target takes lengths, which can no longer be recovered; transformer-corealready carries its sliding/causal mask the same way (MultiHeadAttention.buildSlidingCausalMask,-1e30), and the converter has a second copy of the causal formula in its iota path — a padding mask would be the third copy.
Consumer: SKaiNET-transformers#490 (key-padding mask for MultiHeadAttention, batched BERT/Laya encoder inference) needs this to batch the questions of one typed-decision request instead of running one 322M-parameter encoder pass per question (1.8–5 s each, measured 2026-10-12/13).
🔍 A: ASSESS — Options
keyLengths: Tensor<Int>?operand + recordedmaskKind(proposed): the op gains a[batch]lengths operand and recordsmaskKind ∈ { none, causal, slidingWindow, keyPadding, combined },window,rightContextas parameters. The densemaskstays as the generic fallback, so no caller changes numerically.- Dense mask only, as today: zero API change, but the compiled lane inherits a batch-sized graph input per layer and the fused-kernel path is closed for good.
- A separate
maskedScaledDotProductAttentionop: avoids widening the signature, but doubles the converter, the autograd entry and the backend kernels for one extra operand.
✅ R: RESOLVE — Decision
Option 1, with the mask construction unified:
-
TensorOps.scaledDotProductAttention(query, key, value, mask = null, scale = 0f, causal = false, keyLengths: Tensor<*, *>? = null, window: Int = 0, rightContext: Int = 0);VoidTensorOps,RecordingExecution,ComputeGraphExecutor,DefaultExecutionTapebackward follow.RecordingExecutionrecordsmaskKind,window,rightContextinparametersandkeyLengthsas operand 4. -
One mask builder
AttentionMask.additive(kind, lengths, window, rightContext, seqQ, seqKV)inskainet-lang-core, used by the CPU kernel (DefaultCpuOps.scaledDotProductAttention), by the StableHLO decomposition and, downstream, byMultiHeadAttentionin place ofbuildSlidingCausalMask. Padded keys get-1e30(the value the converter and transformer-core already agree on), never-inf, so a fully padded row stays finite. -
CPU kernel: when
keyLengthsis given, the score loop stops atlen[b]per batch row instead of adding a mask — cheaper than the dense path and bit-identical to it on the attended keys. -
StableHLO lowering, keyed on
OpGranularityPolicy.keepFused("scaleddotproductattention")(the policy is threaded intoConversionContextbut unused so far — this and #1342 are its first consumers):policy emitted form null/false(portable,llvm-cpu)decomposed as today; the padding mask is built from the keyLengthsoperand withiota+compare+selectin the scores shape, so no[b, 1, Sq, Sk]constant enters the moduletrue(vendor target with a fused attention kernel)stablehlo.composite "skainet.sdpa" %q, %k, %v, %lengths { composite_attributes = { mask_kind = "keyPadding", causal = false, window = 128 : i32, right_context = 0 : i32, scale = 0.125 : f32 }, decomposition = @skainet_sdpa_…, version = 1 : i32 }with the decomposition function emitted by the same mask builderBoth rows have identical semantics by construction: the StableHLO spec defines
compositeas replaceable by itsdecomposition, andstablehlo-legalize-composite-to-calldoes that mechanically. TheLoweringSpecrecord and theConversionContext.emitCompositehelper are specified in #1342; this issue reuses them for SDPA rather than adding a second mechanism. -
Autograd:
scaledDotProductAttentionBackwardmasks the gradient of padded keys to zero from the same builder. -
Docs: operator matrix row,
@Lowering(composite = "skainet.sdpa")once #1342 adds the annotation.
🚀 C: COMMIT — Acceptance
-
keyLengths/window/rightContextonTensorOps.scaledDotProductAttention; densemaskpath byte-identical to today -
AttentionMask.additivebuilder shared by the CPU kernel, the StableHLO decomposition and the backward pass; the converter's iota causal path replaced by it -
RecordingExecutionrecordsmaskKind+ lengths operand;ComputeGraphExecutordispatches on them; DIRECT vs OPTIMIZED parity within 1e-6 on a padded batch - StableHLO: lengths-based decomposition and
"skainet.sdpa"composite (version 1) behindOpGranularityPolicy; test runs the composite throughstablehlo-legalize-composite-to-calland compares with the decomposed module - Parity test: padded batch of N sequences equals N unpadded single passes within 1e-5 (CPU, both kernel tiers)
- transformers:
MultiHeadAttentionswitches to the builder and passes lengths (SKaiNET-transformers#490)
Related: #1342 (exact GELU — same LoweringSpec / composite emission seam, first consumers of OpGranularityPolicy together), SKaiNET-transformers#490 (consumer), SKaiNET-transformers#487 (Laya adapter, batchSupport = false today).
- Ngôn ngữ chính
- Kotlin
- Star
- 52
- Fork
- 15
- Merge trung bình
- 1 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 37
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của SKaiNET-developers/SKaiNET
-
coding good first issue platform size:xs skill:js sub-issue
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
SKaiNET-developers/SKaiNET#1232 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
compute-backend dsl/api enhancement size:m skill:kotlin-core skill:numerics
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 12/100
SKaiNET-developers/SKaiNET#1342 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
skeep tracking
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 15/100
SKaiNET-developers/SKaiNET#1331 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
assessment size:s skill:review sub-issue
Độ khó 4/5 1-2 ngày Mức phù hợp với người mới 18/100
SKaiNET-developers/SKaiNET#1330 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
documentation good first issue size:s skill:docs sub-issue
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 78/100
SKaiNET-developers/SKaiNET#1329 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của SKaiNET-developers/SKaiNET
Issue tương tự
-
:maddi-inspection-kotlin:test runs out of heap in a full maddi test run; exit 1 with no failing testĐang mởbuild/ci front-end:kotlin
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
bisq-network/bisq-mobile#1948 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
afk-ok area:data-quality importer size:S
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
enorm-labs/event-junkie#3301 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Negate special case for Long literals uses the wrong valueCó thể đã có người làm @bryantaustin13 đã nhận hôm nay. Đang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
cqframework/clinical_quality_language#1865 ·
Maintainer thường phản hồi trong vòng 8 ngày
-
MDM: interfaceName cannot be set through managed configurationsCó thể đã có người làm @JulienUsson đã nhận hôm nay. Đang mởbug
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 82/100
bk138/droidVNC-NG#404 · 1 bình luận ·