Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
96b0a63
working!
ealmloff Apr 13, 2026
7867d9a
remote
ealmloff Apr 13, 2026
08f2a3d
relex working!
ealmloff Apr 14, 2026
e275069
cli version
ealmloff Apr 14, 2026
40cd435
larger models
ealmloff Apr 14, 2026
7dec8b0
ignore gguf files
ealmloff Apr 14, 2026
1dfb3ec
fix formatting
ealmloff Apr 14, 2026
75579dc
start moving models into rbert
ealmloff Apr 14, 2026
724ade1
dedup some code
ealmloff Apr 14, 2026
2bb8ac6
remove some of the debug prints
ealmloff Apr 14, 2026
aee29dc
cut out some dead code
ealmloff Apr 14, 2026
25614b8
fix rgliner
ealmloff Apr 14, 2026
be018f5
ui demo
ealmloff Apr 14, 2026
f1d419e
chunking
ealmloff Apr 15, 2026
87e8b30
switch to dx components
ealmloff Apr 15, 2026
c8e6d42
rgliner batching
ealmloff Apr 15, 2026
c956136
closer ui
ealmloff Apr 15, 2026
c68e3f3
optimize bilstm
ealmloff Apr 15, 2026
139324f
ui mostly working
ealmloff Apr 15, 2026
b332267
update demo
ealmloff May 30, 2026
cc4f518
Merge origin/main into ner
ealmloff May 30, 2026
2fc0ba1
cache label embeddings
ealmloff May 31, 2026
4b12376
mmap model weights
ealmloff May 31, 2026
f1b6361
use mapped buffer init for model weights
ealmloff Jun 2, 2026
1af2e79
Merge remote-tracking branch 'origin/main' into ner
ealmloff Jun 2, 2026
0e327f7
trim down the diff
ealmloff Jun 2, 2026
5e3b91c
clean up
ealmloff Jun 20, 2026
42e55f5
Merge remote-tracking branch 'origin/main' into ner
ealmloff Jun 20, 2026
a85f6f6
remove demo
ealmloff Jun 20, 2026
fb93866
revert core and llama
ealmloff Jun 20, 2026
c501725
don't force materialize
ealmloff Jun 20, 2026
c20e1f9
clean up implementation
ealmloff Jun 20, 2026
77f95ff
simplify ner
ealmloff Jun 20, 2026
d1a96de
share more attention code
ealmloff Jun 20, 2026
379b318
Merge branch 'main' into ner
ealmloff Jun 20, 2026
4220732
fix gpu
ealmloff Jun 20, 2026
b976c54
fix formatting
ealmloff Jun 20, 2026
1f71ca9
fix clippy
ealmloff Jun 20, 2026
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ tokenizer.json
out.txt
todo.md
rust-analyzer
*.gguf
/.claude
**/.claude/
profiles
54 changes: 40 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ bench = false
[workspace]
members = [
"models/rbert",
"models/rgliner",
"models/kalosm-llama",
"models/kalosm-tokenizer",
"models/rwhisper",
Expand All @@ -29,6 +30,7 @@ members = [
"interfaces/kalosm-streams",
"interfaces/kalosm-parse-macro",
"interfaces/kalosm-common",
"interfaces/kalosm-chunking",
"interfaces/kalosm-model-types",
"fusor-ml/core",
"fusor-ml/gguf",
Expand All @@ -51,13 +53,15 @@ kalosm = { path = "./interfaces/kalosm", version = "0.4.0", default-features = f
kalosm-sample = { path = "./interfaces/kalosm-sample", version = "0.4.0" }
kalosm-parse-macro = { path = "./interfaces/kalosm-parse-macro", version = "0.4.0" }
kalosm-common = { path = "./interfaces/kalosm-common", version = "0.4.0" }
kalosm-chunking = { path = "./interfaces/kalosm-chunking", version = "0.4.0" }
kalosm-model-types = { path = "./interfaces/kalosm-model-types", version = "0.4.0" }
kalosm-language-model = { path = "./interfaces/language-model", version = "0.4.0" }
kalosm-streams = { path = "./interfaces/kalosm-streams", version = "0.4.0" }
kalosm-language = { path = "./interfaces/kalosm-language", version = "0.4.0", default-features = false }
kalosm-sound = { path = "./interfaces/kalosm-sound", version = "0.4.0", default-features = false }
kalosm-vision = { path = "./interfaces/kalosm-vision", version = "0.4.0", default-features = false }
rbert = { path = "./models/rbert", version = "0.4.0", default-features = false }
rgliner = { path = "./models/rgliner", version = "0.4.0" }
kalosm-llama = { path = "./models/kalosm-llama", version = "0.4.0", default-features = false }
kalosm-tokenizer = { path = "./models/kalosm-tokenizer", version = "0.4.0" }
rwhisper = { path = "./models/rwhisper", version = "0.4.0", default-features = false }
Expand Down
40 changes: 23 additions & 17 deletions fusor-ml/core/src/compute_graph/resolve/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,18 @@ impl Resolver {
let encode_start = host_trace.then(Instant::now);
let mut dispatch_index = 0usize;
let mut command_index = 0usize;
let dispatches_per_pass = dispatches_per_pass(total_kernels);
// Bound the cumulative workgroups recorded into a single compute pass by
// the device's real per-dimension workgroup limit. Each
// `begin_compute_pass` is a GPU command-encoder; recording too many
// passes into one command buffer loses the device on Metal (a
// long-sequence encoder + BiLSTM resolves to ~2200 dispatches, and one
// pass per dispatch — the old policy for large graphs — meant ~2200
// passes, which faults; the same dispatches grouped into a handful of
// passes run fine). Grouping by the device-reported workgroup limit
// keeps the pass count at roughly `total_workgroups / limit`: a few
// dozen for the largest graphs, one for decode/prefill — no threshold.
let pass_workgroup_budget =
u64::from(device.limits().max_compute_workgroups_per_dimension);
while command_index < commands.len() {
match &commands[command_index] {
CommandRecord::CopyBuffer(copy) => {
Expand Down Expand Up @@ -577,14 +588,20 @@ impl Resolver {
label: Some("Resolver Direct Kernels"),
timestamp_writes: None,
});
let mut pass_dispatches = 0usize;
let mut pass_workgroups = 0u64;
while command_index < commands.len() {
if pass_dispatches >= dispatches_per_pass {
break;
}
let CommandRecord::Dispatch(record) = &commands[command_index] else {
break;
};
let dispatch_workgroups = record.dispatch.workgroup_count();
// Always record at least one dispatch per pass; otherwise
// close the pass before its cumulative workgroups would
// exceed the device budget.
if pass_workgroups > 0
&& pass_workgroups + dispatch_workgroups > pass_workgroup_budget
{
break;
}
if let Some((query_set, _, _, _)) = &query_resources {
pass.write_timestamp(query_set, (dispatch_index * 2) as u32);
}
Expand All @@ -596,7 +613,7 @@ impl Resolver {
}
dispatch_index += 1;
command_index += 1;
pass_dispatches += 1;
pass_workgroups += dispatch_workgroups;
}
}
}
Expand Down Expand Up @@ -715,14 +732,3 @@ fn direct_plan_binding_buffers(inputs: &[MirValue]) -> Vec<Vec<std::sync::Arc<wg
.collect();
vec![buffers]
}

fn dispatches_per_pass(total_kernels: usize) -> usize {
if let Ok(value) = std::env::var("FUSOR_RESOLVE_DISPATCHES_PER_PASS")
&& let Ok(parsed) = value.parse::<usize>()
&& parsed > 0
{
return parsed;
}

if total_kernels >= 1024 { 1 } else { usize::MAX }
}
3 changes: 2 additions & 1 deletion fusor-ml/cpu/benches/comparison.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use candle_core::{Device, Tensor as CandleTensor};
use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main};
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use fusor_cpu::__private::TypedTensor;
use std::hint::black_box;

const SIZES: &[usize] = &[64, 256];

Expand Down
3 changes: 2 additions & 1 deletion fusor-ml/cpu/benches/fusion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
//! memory multiple times (once per operation).

use candle_core::{Device, Tensor as CandleTensor};
use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main};
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use fusor_cpu::__private::{ConcreteTensor, TypedTensor};
use std::hint::black_box;

/// Benchmark fused operations (single memory pass) vs separate operations (multiple passes)
fn bench_fusion(c: &mut Criterion) {
Expand Down
3 changes: 2 additions & 1 deletion fusor-ml/cpu/benches/qmatmul.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use aligned_vec::AVec;
use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main};
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use fusor_cpu::__private::{ConcreteTensor, QuantizedTensor, TypedTensor};
use fusor_cpu::BlockQ8_0;
use half::f16;
use std::hint::black_box;

/// Helper to create a Q8_0 block from scale and data
fn make_q8_0_block(scale: f32, data: [i8; 32]) -> BlockQ8_0 {
Expand Down
3 changes: 2 additions & 1 deletion fusor-ml/cpu/benches/tensor_ops.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use criterion::{BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main};
use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use fusor_cpu::__private::{Abs, Add, ConcreteTensor, Div, Mul, Neg, Sqrt, Sub, TensorBacking};
use std::hint::black_box;

const SIZES: &[usize] = &[64, 256];

Expand Down
6 changes: 6 additions & 0 deletions fusor-ml/fusor/src/composite/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod reductions;
mod rope;
mod shape;
mod to_vec;
mod transformer;
mod upsample;
mod where_cond;

Expand All @@ -25,3 +26,8 @@ pub use rope::{RopeCache, base_inverse_frequency};
pub(crate) use shape::broadcast_shapes;
pub use shape::{arange, arange_step, cat, stack};
pub use to_vec::{ToVec, ToVec1, ToVec2, ToVec3};
pub use transformer::{
AttentionBias, AttentionVariant, FeedForwardVariant, GatedActivation, GroupedAttention,
LlamaFeedForward, Norm, PhiFeedForward, RopeLike, SeparateAttention, TransformerBlock,
forward_attention_qkv_f32,
};
Loading
Loading