66// Runs both over the same audio, reports median wall time + real-time factor.
77//
88// Usage:
9- // bench_a2_fast [--buffer N] [--seconds S] [--iters I] <model.nam> [<model.nam> ...]
9+ // bench_a2_fast [--buffer N] [--seconds S] [--iters I] [--slim V] <model.nam> [<model.nam> ...]
10+ //
11+ // A model may be a plain WaveNet .nam or a SlimmableContainer .nam (e.g. an A2 file
12+ // bundling A2-Full + A2-Lite submodels). For a container, --slim V (0.0-1.0) selects the
13+ // submodel exactly as ContainerModel::SetSlimmableSize would (first submodel whose
14+ // max_value exceeds V, else the last); the selected submodel is then benched fast vs generic.
1015//
1116// Only compiled when NAM_ENABLE_A2_FAST is defined.
1217
@@ -44,9 +49,13 @@ struct Options
4449 int buffer_size = 64 ;
4550 double seconds = 2.0 ;
4651 int iterations = 10 ;
52+ double slim = 1.0 ; // SlimmableContainer selector; defaults to full size (last submodel)
53+ bool has_slim = false ;
4754 std::vector<std::string> model_paths;
4855};
4956
57+ const char * kUsage = " Usage: bench_a2_fast [--buffer N] [--seconds S] [--iters I] [--slim V] <model.nam> ...\n " ;
58+
5059Options parse_args (int argc, char ** argv)
5160{
5261 Options o;
@@ -59,9 +68,19 @@ Options parse_args(int argc, char** argv)
5968 o.seconds = std::atof (argv[++i]);
6069 else if (a == " --iters" && i + 1 < argc)
6170 o.iterations = std::atoi (argv[++i]);
71+ else if (a == " --slim" && i + 1 < argc)
72+ {
73+ o.slim = std::atof (argv[++i]);
74+ o.has_slim = true ;
75+ if (o.slim < 0.0 || o.slim > 1.0 )
76+ {
77+ std::cerr << " --slim value must be between 0.0 and 1.0\n " ;
78+ std::exit (1 );
79+ }
80+ }
6281 else if (a == " -h" || a == " --help" )
6382 {
64- std::cerr << " Usage: bench_a2_fast [--buffer N] [--seconds S] [--iters I] <model.nam> ... \n " ;
83+ std::cerr << kUsage ;
6584 std::exit (0 );
6685 }
6786 else
@@ -78,7 +97,33 @@ struct LoadedModel
7897 std::string path;
7998};
8099
81- LoadedModel load_nam (const std::string& path)
100+ // Select a SlimmableContainer submodel for the given slim value, mirroring
101+ // ContainerModel::SetSlimmableSize: the first submodel whose max_value exceeds the value,
102+ // else the last. Returns the chosen submodel's model spec and appends a label to `path`.
103+ nlohmann::json select_container_submodel (const nlohmann::json& config, double slim, std::string& path)
104+ {
105+ const auto & submodels = config[" submodels" ];
106+ if (!submodels.is_array () || submodels.empty ())
107+ throw std::runtime_error (path + " : SlimmableContainer 'submodels' must be a non-empty array" );
108+
109+ size_t idx = submodels.size () - 1 ;
110+ for (size_t i = 0 ; i < submodels.size (); i++)
111+ {
112+ if (slim < submodels[i].at (" max_value" ).get <double >())
113+ {
114+ idx = i;
115+ break ;
116+ }
117+ }
118+
119+ std::ostringstream label;
120+ label << path << " [slim=" << slim << " -> submodel " << idx << " /" << submodels.size ()
121+ << " , max_value=" << submodels[idx].at (" max_value" ).get <double >() << " ]" ;
122+ path = label.str ();
123+ return submodels[idx].at (" model" );
124+ }
125+
126+ LoadedModel load_nam (const std::string& path, const Options& o)
82127{
83128 LoadedModel m;
84129 m.path = path;
@@ -87,8 +132,22 @@ LoadedModel load_nam(const std::string& path)
87132 throw std::runtime_error (" Could not open " + path);
88133 nlohmann::json j;
89134 is >> j;
90- if (j.value (" architecture" , std::string ()) != " WaveNet" )
91- throw std::runtime_error (path + " : not a WaveNet model" );
135+
136+ // Resolve a SlimmableContainer to the submodel selected by --slim (each submodel is a
137+ // full, standalone model spec). A plain WaveNet is used directly.
138+ std::string arch = j.value (" architecture" , std::string ());
139+ if (arch == " SlimmableContainer" )
140+ {
141+ j = select_container_submodel (j[" config" ], o.slim , m.path );
142+ arch = j.value (" architecture" , std::string ());
143+ }
144+ else if (o.has_slim )
145+ {
146+ std::cerr << " [note] " << path << " : --slim ignored (not a SlimmableContainer)\n " ;
147+ }
148+
149+ if (arch != " WaveNet" )
150+ throw std::runtime_error (path + " : not a WaveNet model (architecture=" + arch + " )" );
92151 m.config = j[" config" ];
93152 m.weights = j[" weights" ].get <std::vector<float >>();
94153 if (j.contains (" sample_rate" ) && !j[" sample_rate" ].is_null ())
@@ -244,14 +303,14 @@ int main(int argc, char** argv)
244303 Options o = parse_args (argc, argv);
245304 if (o.model_paths .empty ())
246305 {
247- std::cerr << " Usage: bench_a2_fast [--buffer N] [--seconds S] [--iters I] <model.nam> ... \n " ;
306+ std::cerr << kUsage ;
248307 return 1 ;
249308 }
250309 for (const auto & p : o.model_paths )
251310 {
252311 try
253312 {
254- bench_model (load_nam (p), o);
313+ bench_model (load_nam (p, o ), o);
255314 }
256315 catch (const std::exception& e)
257316 {
0 commit comments