Skip to content

Commit 03ba000

Browse files
author
zhangjian
committed
update
1 parent 58b1722 commit 03ba000

11 files changed

Lines changed: 578 additions & 703 deletions

File tree

Cargo.toml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ anyhow = { version = "1" }
1616
slsl = { version = "0.0.7", features = ["rayon"], optional = true }
1717
aksr = { version = "0.0.7" }
1818
ab_glyph = { version = "0.2.32" }
19-
image = { version = "0.25" }
20-
imageproc = { version = "0.25" }
19+
image = { version = "0.25", default-features = false, features = [
20+
"jpeg", "png", "gif", "webp", "bmp", "ico", "rayon"
21+
] }
22+
imageproc = { version = "0.25", default-features = false, features = ["rayon"] }
2123
ndarray = { version = "0.16.1", features = ["rayon"] }
2224
half = { version = "2.7.1", features = ["bytemuck", "num-traits"] }
2325
indicatif = { version = "0.18" }
@@ -35,7 +37,7 @@ dirs = { version = "6.0.0" }
3537
chrono = { version = "0.4.40" }
3638
regex = { version = "1.12.2" }
3739
tempfile = { version = "3.23.0" }
38-
fast_image_resize = { version = "=5.1.4", features = ["image", "rayon"] }
40+
fast_image_resize = { version = "=5.1.4", default-features = false, features = ["image", "rayon"] }
3941
minifb = { version = "0.28.0", optional = true }
4042
video-rs = { version = "0.10.3", features = ["ndarray"], optional = true }
4143
ndarray-npy = { version = "0.9.1", optional = true }
@@ -46,6 +48,7 @@ ort = { version = "=2.0.0-rc.10", default-features = false, optional = true, fea
4648
] }
4749
hf-hub = { version = "0.4.3", default-features = false, features = ["ureq", "native-tls"], optional = true }
4850
tokenizers = { version = "0.22.1", optional = true }
51+
lru = "0.16.2"
4952

5053

5154
[dev-dependencies]
@@ -54,9 +57,13 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter", "chrono"] }
5457

5558

5659
[profile.dev]
57-
opt-level = 1
60+
opt-level = 0
5861
incremental = true
5962

63+
# Optimize dependencies in dev mode (faster runtime, slightly slower first compile)
64+
[profile.dev.package."*"]
65+
opt-level = 2
66+
6067
[profile.release]
6168
opt-level = 3
6269
lto = "fat"

examples/sam3/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ cargo run -r -F sam3,cuda --example sam3 -- \
1414

1515
# Multiple prompts on multiple images
1616
cargo run -r -F sam3,cuda --example sam3 -- \
17-
--device cuda --dtype q4f16 --batch 2 \
17+
--device cuda --dtype q4f16 --vision-batch 2 \
1818
--source assets/sam3-demo.jpg --source assets/bus.jpg \
1919
-p bus -p cat -p shoe -p cellphone -p person -p "short hair"
2020

examples/sam3/main.rs

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,7 @@ struct Args {
1212
device: String,
1313

1414
/// source image paths (can specify multiple)
15-
#[argh(
16-
option,
17-
default = "vec![
18-
String::from(\"./assets/sam3-demo.jpg\"),
19-
// String::from(\"./assets/bus.jpg\")
20-
]"
21-
)]
15+
#[argh(option, default = "vec![String::from(\"./assets/sam3-demo.jpg\")]")]
2216
source: Vec<String>,
2317

2418
/// prompts: "text;pos:x,y,w,h;neg:x,y,w,h" (can specify multiple)
@@ -29,37 +23,61 @@ struct Args {
2923
#[argh(option, default = "0.5")]
3024
conf: f32,
3125

32-
/// image batch size min
26+
/// show mask
27+
#[argh(switch)]
28+
show_mask: bool,
29+
30+
/// dtype
31+
#[argh(option, default = "String::from(\"q4f16\")")]
32+
dtype: String,
33+
34+
/// vision encoder batch min
3335
#[argh(option, default = "1")]
34-
batch_min: usize,
36+
vision_batch_min: usize,
3537

36-
/// image batch size
38+
/// vision encoder batch opt
3739
#[argh(option, default = "1")]
38-
batch: usize,
40+
vision_batch: usize,
3941

40-
/// image batch size max
42+
/// vision encoder batch max
4143
#[argh(option, default = "8")]
42-
batch_max: usize,
44+
vision_batch_max: usize,
4345

44-
/// text batch size min
46+
/// text encoder batch min
4547
#[argh(option, default = "1")]
4648
text_batch_min: usize,
4749

48-
/// text batch size
50+
/// text encoder batch opt
4951
#[argh(option, default = "4")]
5052
text_batch: usize,
5153

52-
/// text batch size max
54+
/// text encoder batch max
5355
#[argh(option, default = "16")]
5456
text_batch_max: usize,
5557

56-
/// dtype
57-
#[argh(option, default = "String::from(\"q4f16\")")]
58-
dtype: String,
58+
/// geometry encoder batch min
59+
#[argh(option, default = "1")]
60+
geo_batch_min: usize,
5961

60-
/// show mask
61-
#[argh(switch)]
62-
show_mask: bool,
62+
/// geometry encoder batch opt
63+
#[argh(option, default = "8")]
64+
geo_batch: usize,
65+
66+
/// geometry encoder batch max
67+
#[argh(option, default = "16")]
68+
geo_batch_max: usize,
69+
70+
/// decoder batch min
71+
#[argh(option, default = "1")]
72+
decoder_batch_min: usize,
73+
74+
/// decoder batch opt
75+
#[argh(option, default = "1")]
76+
decoder_batch: usize,
77+
78+
/// decoder batch max
79+
#[argh(option, default = "8")]
80+
decoder_batch_max: usize,
6381
}
6482

6583
fn main() -> Result<()> {
@@ -80,16 +98,28 @@ fn main() -> Result<()> {
8098
.collect::<std::result::Result<Vec<_>, _>>()
8199
.map_err(|e| anyhow::anyhow!("{}", e))?;
82100

83-
// Build model
101+
// Build model with per-encoder batch sizes
84102
let config = Config::sam3_image_predictor()
85103
.with_dtype_all(args.dtype.parse()?)
86104
.with_class_confs(&[args.conf])
87-
.with_batch_size_all_min_opt_max(args.batch_min, args.batch, args.batch_max)
105+
// Per-encoder batch sizes for TensorRT (min, opt, max)
106+
.with_visual_encoder_batch_min_opt_max(
107+
args.vision_batch_min,
108+
args.vision_batch,
109+
args.vision_batch_max,
110+
)
88111
.with_textual_encoder_batch_min_opt_max(
89112
args.text_batch_min,
90113
args.text_batch,
91114
args.text_batch_max,
92115
)
116+
.with_encoder_batch_min_opt_max(args.geo_batch_min, args.geo_batch, args.geo_batch_max)
117+
.with_decoder_batch_min_opt_max(
118+
args.decoder_batch_min,
119+
args.decoder_batch,
120+
args.decoder_batch_max,
121+
)
122+
// Device configuration
93123
// => If your GPU memory is insufficient, you can place some modules on CPU
94124
// .with_visual_encoder_device(args.device.parse()?)
95125
// .with_textual_encoder_device(args.device.parse()?)
@@ -109,7 +139,7 @@ fn main() -> Result<()> {
109139

110140
// DataLoader with batch iteration
111141
let dataloader = DataLoader::from_paths(&args.source)?
112-
.with_batch(args.batch)
142+
.with_batch(args.vision_batch)
113143
.with_progress_bar(true)
114144
.build()?;
115145

@@ -125,10 +155,10 @@ fn main() -> Result<()> {
125155
}
126156
}
127157

128-
// Cache info
129-
let (cached_count, mem_mb) = model.cache_stats();
130-
println!("Cache: {} texts, ~{}MB", cached_count, mem_mb);
158+
// Cache stats
159+
model.cache_stats();
131160

161+
// Performance stats
132162
usls::perf(false);
133163

134164
Ok(())

src/core/config.rs

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -236,46 +236,6 @@ impl Config {
236236
self
237237
}
238238

239-
pub fn with_textual_encoder_batch_min_opt_max(
240-
mut self,
241-
min: usize,
242-
opt: usize,
243-
max: usize,
244-
) -> Self {
245-
self.textual_encoder = self.textual_encoder.with_ixx(0, 0, (min, opt, max).into());
246-
self
247-
}
248-
249-
pub fn with_visual_encoder_batch_min_opt_max(
250-
mut self,
251-
min: usize,
252-
opt: usize,
253-
max: usize,
254-
) -> Self {
255-
self.visual_encoder = self.visual_encoder.with_ixx(0, 0, (min, opt, max).into());
256-
self
257-
}
258-
259-
pub fn with_encoder_encoder_batch_min_opt_max(
260-
mut self,
261-
min: usize,
262-
opt: usize,
263-
max: usize,
264-
) -> Self {
265-
self.encoder = self.encoder.with_ixx(0, 0, (min, opt, max).into());
266-
self
267-
}
268-
269-
pub fn with_decoder_batch_min_opt_max(mut self, min: usize, opt: usize, max: usize) -> Self {
270-
self.decoder = self.decoder.with_ixx(0, 0, (min, opt, max).into());
271-
self
272-
}
273-
274-
pub fn with_model_batch_min_opt_max(mut self, min: usize, opt: usize, max: usize) -> Self {
275-
self.model = self.model.with_ixx(0, 0, (min, opt, max).into());
276-
self
277-
}
278-
279239
pub fn with_batch_size_all(mut self, batch_size: usize) -> Self {
280240
self.visual = self.visual.with_ixx(0, 0, batch_size.into());
281241
self.textual = self.textual.with_ixx(0, 0, batch_size.into());
@@ -860,3 +820,30 @@ impl_ort_config_methods!(Config, coord_decoder);
860820
impl_ort_config_methods!(Config, visual_projection);
861821
impl_ort_config_methods!(Config, textual_projection);
862822
impl_processor_config_methods!(Config, processor);
823+
824+
/// Macro to generate `with_*_batch_min_opt_max` methods for Config
825+
macro_rules! impl_batch_min_opt_max {
826+
($ty:ty, $field:ident) => {
827+
impl $ty {
828+
paste::paste! {
829+
pub fn [<with_ $field _batch_min_opt_max>](mut self, min: usize, opt: usize, max: usize) -> Self {
830+
self.$field = self.$field.with_ixx(0, 0, (min, opt, max).into());
831+
self
832+
}
833+
}
834+
}
835+
};
836+
}
837+
838+
// Batch size configuration methods
839+
impl_batch_min_opt_max!(Config, model);
840+
impl_batch_min_opt_max!(Config, visual);
841+
impl_batch_min_opt_max!(Config, textual);
842+
impl_batch_min_opt_max!(Config, encoder);
843+
impl_batch_min_opt_max!(Config, decoder);
844+
impl_batch_min_opt_max!(Config, visual_encoder);
845+
impl_batch_min_opt_max!(Config, textual_encoder);
846+
impl_batch_min_opt_max!(Config, visual_decoder);
847+
impl_batch_min_opt_max!(Config, textual_decoder);
848+
impl_batch_min_opt_max!(Config, visual_projection);
849+
impl_batch_min_opt_max!(Config, textual_projection);

src/core/dtype.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ impl std::str::FromStr for DType {
6666
}
6767
}
6868

69+
impl DType {
70+
pub fn size_in_bytes(self) -> usize {
71+
match self {
72+
Self::Auto => 4, // default to f32
73+
Self::Int4 | Self::Uint4 | Self::Bnb4 | Self::Q4 | Self::Fp4e2m1 => 1, // sub-byte, min 1
74+
Self::Int8 | Self::Uint8 | Self::Q8 => 1,
75+
Self::Fp8e4m3fn | Self::Fp8e4m3fnuz | Self::Fp8e5m2 | Self::Fp8e5m2fnuz => 1,
76+
Self::Int16 | Self::Uint16 | Self::Fp16 | Self::Bf16 | Self::Q4f16 => 2,
77+
Self::Int32 | Self::Uint32 | Self::Fp32 => 4,
78+
Self::Int64 | Self::Uint64 | Self::Fp64 | Self::Complex64 => 8,
79+
Self::Complex128 => 16,
80+
}
81+
}
82+
}
83+
6984
impl std::fmt::Display for DType {
7085
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
7186
let x = match self {

src/core/engine.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ impl From<TensorElementType> for DType {
4040
TensorElementType::Float8E5M2FNUZ => Self::Fp8e5m2fnuz,
4141
TensorElementType::Complex64 => Self::Complex64,
4242
TensorElementType::Complex128 => Self::Complex128,
43-
_ => todo!(),
43+
TensorElementType::Bool => Self::Uint8,
44+
TensorElementType::String | TensorElementType::Undefined => Self::Auto,
4445
}
4546
}
4647
}

src/models/sam3/README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,29 +70,35 @@ Outputs:
7070

7171
## TensorRT Conversion
7272

73+
### Vision Encoder
7374
```bash
74-
# Vision Encoder
7575
trtexec --onnx=sam3_vision_encoder.onnx \
7676
--minShapes=images:1x3x1008x1008 \
7777
--optShapes=images:4x3x1008x1008 \
7878
--maxShapes=images:8x3x1008x1008 \
7979
--saveEngine=sam3_vision_encoder.engine
80+
```
8081

81-
# Text Encoder
82+
### Text Encoder
83+
```bash
8284
trtexec --onnx=sam3_text_encoder.onnx \
8385
--minShapes=input_ids:1x32,attention_mask:1x32 \
8486
--optShapes=input_ids:4x32,attention_mask:4x32 \
8587
--maxShapes=input_ids:8x32,attention_mask:8x32 \
8688
--saveEngine=sam3_text_encoder.engine
89+
```
8790

88-
# Geometry Encoder
91+
### Geometry Encoder
92+
```bash
8993
trtexec --onnx=sam3_geometry_encoder.onnx \
9094
--minShapes=input_boxes:1x1x4,input_boxes_labels:1x1,fpn_feat:1x256x72x72,fpn_pos:1x256x72x72 \
9195
--optShapes=input_boxes:1x5x4,input_boxes_labels:1x5,fpn_feat:1x256x72x72,fpn_pos:1x256x72x72 \
9296
--maxShapes=input_boxes:8x20x4,input_boxes_labels:8x20,fpn_feat:8x256x72x72,fpn_pos:8x256x72x72 \
9397
--saveEngine=sam3_geometry_encoder.engine
98+
```
9499

95-
# Decoder
100+
### Decoder
101+
```bash
96102
trtexec --onnx=sam3_decoder.onnx \
97103
--minShapes=fpn_feat_0:1x256x288x288,fpn_feat_1:1x256x144x144,fpn_feat_2:1x256x72x72,fpn_pos_2:1x256x72x72,prompt_features:1x1x256,prompt_mask:1x1 \
98104
--optShapes=fpn_feat_0:1x256x288x288,fpn_feat_1:1x256x144x144,fpn_feat_2:1x256x72x72,fpn_pos_2:1x256x72x72,prompt_features:1x33x256,prompt_mask:1x33 \

src/models/sam3/config.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,25 @@ use crate::Config;
33
/// Model configuration for `SAM3`
44
impl Config {
55
/// SAM3 base configuration
6-
///
7-
/// - Input size: 1008x1008 (FitExact, no aspect ratio preserved)
8-
/// - Normalization: mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]
9-
/// - Tokenizer: CLIP BPE (max_length=32)
10-
/// - Confidence threshold: 0.5
116
pub fn sam3() -> Self {
127
Self::default()
138
.with_name("sam3")
149
.with_num_dry_run_all(1)
15-
.with_batch_size_all_min_opt_max(1, 1, 10)
10+
// Batch sizes: vision=1, text=4, geometry=8, decoder=1
11+
.with_visual_encoder_batch_min_opt_max(1, 1, 8)
12+
.with_textual_encoder_batch_min_opt_max(1, 4, 16)
13+
.with_encoder_batch_min_opt_max(1, 8, 16) // geometry encoder
14+
.with_decoder_batch_min_opt_max(1, 1, 8) // decoder (memory intensive)
15+
// Shape configurations
1616
.with_visual_encoder_ixx(0, 1, 3.into()) // vision-encoder: channels
1717
.with_visual_encoder_ixx(0, 2, 1008.into()) // vision-encoder: height
1818
.with_visual_encoder_ixx(0, 3, 1008.into()) // vision-encoder: width
19-
.with_textual_encoder_ixx(0, 1, 32.into()) // text-encoder: text sequence length
20-
.with_encoder_ixx(0, 1, (1, 2, 8).into()) // geometry-encoder: input_boxes, num_boxes
21-
.with_encoder_ixx(1, 1, (1, 2, 8).into()) // geometry-encoder: input_boxes_labels, num_boxes
22-
.with_decoder_ixx(4, 1, (1, 34, 60).into()) // decoder: prompt_features prompt_len
23-
.with_decoder_ixx(5, 1, (1, 34, 60).into()) // decoder: prompt_mask prompt_len
19+
.with_textual_encoder_ixx(0, 1, 32.into()) // text-encoder: sequence length
20+
.with_encoder_ixx(0, 1, (1, 2, 8).into()) // geometry-encoder: num_boxes
21+
.with_encoder_ixx(1, 1, (1, 2, 8).into()) // geometry-encoder: num_boxes
22+
.with_decoder_ixx(4, 1, (1, 34, 60).into()) // decoder: prompt_len
23+
.with_decoder_ixx(5, 1, (1, 34, 60).into()) // decoder: prompt_len
24+
// Preprocessing
2425
.with_resize_mode(crate::ResizeMode::FitExact)
2526
.with_resize_filter("Bilinear")
2627
.with_image_mean(&[0.5, 0.5, 0.5])

0 commit comments

Comments
 (0)