1+ use rustc_hash:: FxHashMap ;
12/// NCHWc layout coverage probe — Step 0 of NCHWc-everywhere plan.
23///
34/// Loads a tracker ONNX model and classifies every Conv op as NCHWc-eligible
78/// Usage:
89/// cargo run --release --no-default-features -p yscv-llm-bench --bin nchwc_coverage \
910/// -- private/private/model.onnx
10- use std:: collections:: { HashMap , HashSet } ;
11-
11+ use rustc_hash:: FxHashSet ;
1212use yscv_onnx:: { OnnxAttribute , OnnxModel , OnnxNode , load_onnx_model_from_file} ;
1313
1414fn main ( ) {
@@ -76,8 +76,8 @@ fn is_passthrough(op_type: &str) -> bool {
7676/// Build a map: tensor_name → shape, tracing through Identity nodes to
7777/// resolve weight-sharing aliases. In Siamese networks, branch1 weights
7878/// are Identity(branch0_initializer) — treat them as static weights.
79- fn build_effective_initializers ( model : & OnnxModel ) -> HashMap < String , Vec < usize > > {
80- let mut effective: HashMap < String , Vec < usize > > = model
79+ fn build_effective_initializers ( model : & OnnxModel ) -> FxHashMap < String , Vec < usize > > {
80+ let mut effective: FxHashMap < String , Vec < usize > > = model
8181 . initializers
8282 . iter ( )
8383 . map ( |( k, v) | ( k. clone ( ) , v. shape ( ) . to_vec ( ) ) )
@@ -139,8 +139,8 @@ fn run_coverage_probe(model: &OnnxModel) {
139139 // Classify each conv op
140140 let mut eligible = 0usize ;
141141 let mut rejected = 0usize ;
142- let mut kind_counts: HashMap < String , usize > = HashMap :: new ( ) ;
143- let mut reject_reasons: HashMap < String , usize > = HashMap :: new ( ) ;
142+ let mut kind_counts: FxHashMap < String , usize > = FxHashMap :: default ( ) ;
143+ let mut reject_reasons: FxHashMap < String , usize > = FxHashMap :: default ( ) ;
144144
145145 for ( _, node) in & conv_ops {
146146 let weight_name = node. inputs . get ( 1 ) . map ( |s| s. as_str ( ) ) . unwrap_or ( "" ) ;
@@ -331,7 +331,7 @@ fn run_coverage_probe(model: &OnnxModel) {
331331 println ! ( ) ;
332332 println ! ( "QLinearConv ops in model: {}" , qlinear_conv. len( ) ) ;
333333 // Show all non-Conv node op types and counts
334- let mut op_counts: HashMap < & str , usize > = HashMap :: new ( ) ;
334+ let mut op_counts: FxHashMap < & str , usize > = FxHashMap :: default ( ) ;
335335 for node in & model. nodes {
336336 * op_counts. entry ( node. op_type . as_str ( ) ) . or_default ( ) += 1 ;
337337 }
@@ -349,7 +349,7 @@ fn run_coverage_probe(model: &OnnxModel) {
349349 // Non-passthrough, non-Conv ops require NHWC → insert converter at boundary
350350
351351 // Build tensor → producing node index
352- let mut tensor_producer: HashMap < & str , usize > = HashMap :: new ( ) ;
352+ let mut tensor_producer: FxHashMap < & str , usize > = FxHashMap :: default ( ) ;
353353 for ( i, node) in model. nodes . iter ( ) . enumerate ( ) {
354354 for out in & node. outputs {
355355 if !out. is_empty ( ) {
@@ -421,8 +421,8 @@ fn run_coverage_probe(model: &OnnxModel) {
421421 // And number of exit converters (nchwc tensors consumed by non-nchwc non-Conv nodes)
422422
423423 // Use effective_weights keys as the "static" set (includes Identity-aliased weights)
424- let static_names: HashSet < & str > = effective_weights. keys ( ) . map ( |s| s. as_str ( ) ) . collect ( ) ;
425- let initializer_names: HashSet < & str > = static_names. clone ( ) ;
424+ let static_names: FxHashSet < & str > = effective_weights. keys ( ) . map ( |s| s. as_str ( ) ) . collect ( ) ;
425+ let initializer_names: FxHashSet < & str > = static_names. clone ( ) ;
426426 let dynamic_inputs: Vec < & str > = model
427427 . inputs
428428 . iter ( )
@@ -437,7 +437,7 @@ fn run_coverage_probe(model: &OnnxModel) {
437437 }
438438
439439 // Mark which tensors are in nchwc domain (after potential converter)
440- let mut nchwc_tensors: HashSet < String > = HashSet :: new ( ) ;
440+ let mut nchwc_tensors: FxHashSet < String > = FxHashSet :: default ( ) ;
441441 // Graph inputs start as NHWC; we will count converters needed for them
442442 // if any eligible node consumes them directly.
443443
@@ -446,7 +446,7 @@ fn run_coverage_probe(model: &OnnxModel) {
446446 let mut internal_boundaries = 0usize ;
447447
448448 // Track which dynamic inputs get a converter
449- let mut converted_inputs: HashSet < String > = HashSet :: new ( ) ;
449+ let mut converted_inputs: FxHashSet < String > = FxHashSet :: default ( ) ;
450450
451451 for ( i, node) in model. nodes . iter ( ) . enumerate ( ) {
452452 if !node_eligible[ i] && !matches ! ( node. op_type. as_str( ) , "Conv" | "Conv_Relu" | "Conv_SiLU" )
0 commit comments