Skip to content

Commit 32cfc75

Browse files
committed
Merge branch 'main' of https://github.com/sdatkinson/NeuralAmpModelerCore into fix-test
2 parents f98903d + f869e9c commit 32cfc75

1 file changed

Lines changed: 66 additions & 7 deletions

File tree

tools/bench_a2_fast.cpp

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
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+
5059
Options 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

Comments
 (0)