74 std::size_t initSample, std::size_t sampleSize) {
75 if (traces.empty())
throw InputError(
"infer_minps_setup: no classes");
76 if (initSample < 1)
throw InputError(
"infer_minps_setup: initSample is 1-based");
79 std::vector<std::vector<double>> at_ms, rt;
81 for (std::size_t k = 0; k < traces.size(); ++k) {
82 if (traces[k].arrival_ms.size() != traces[k].rt.size())
84 "infer_minps_setup: a class's arrival and response vectors disagree in length");
85 if (traces[k].rt.empty())
continue;
86 at_ms.push_back(traces[k].arrival_ms);
87 rt.push_back(traces[k].rt);
90 const std::size_t R = at_ms.size();
91 if (R == 0)
throw InputError(
"infer_minps_setup: every class is empty");
100 std::vector<double> ql;
102 std::vector<Row> rows;
103 for (std::size_t k = 0; k < R; ++k)
104 for (std::size_t i = 0; i < rt[k].size(); ++i) {
106 r.at = at_ms[k][i] / 1000.0;
110 for (std::size_t c = 0; c < R && c < qls[k].cols(); ++c) r.ql[c] = qls[k](i, c);
113 std::stable_sort(rows.begin(), rows.end(),
114 [](
const Row& a,
const Row& b) { return a.at < b.at; });
118 double Wexp = 0.0, qlTotal = 0.0;
119 for (std::size_t i = 0; i < rows.size(); ++i) {
121 for (std::size_t c = 0; c < R; ++c) s += rows[i].ql[c];
122 Wexp = std::max(Wexp, s);
126 double numNotProc = Wexp - qlTotal /
static_cast<double>(rows.size());
127 numNotProc /=
static_cast<double>(R);
130 if (sampleSize == 0) sampleSize = rows.size();
131 if (initSample - 1 + sampleSize > rows.size())
133 "infer_minps_setup: the requested window runs past the end of the trace; a window is "
134 "contiguous by construction and cannot be shortened silently");
135 const std::size_t first = initSample - 1, last = first + sampleSize - 1;
137 std::vector<std::size_t> perClass(R, 0);
138 for (std::size_t i = first; i <= last; ++i) ++perClass[rows[i].cls - 1];
141 const double span = rows[last].at + rows[last].rt - rows[first].at;
142 out.
lambda.assign(R, 1e6);
143 for (std::size_t k = 0; k < R; ++k) {
145 if (span > 0.0 && numNotProc != 0.0)
146 v = (
static_cast<double>(perClass[k]) / span) / numNotProc;
149 if (!(v >= 0.0)) v = 1e6;
150 out.
lambda[k] = std::min(1e6, v);
154 for (std::size_t i = first; i <= last; ++i) {
155 if (!(rows[i].rt > 0.0))
continue;
163 throw InputError(
"infer_minps_setup: the window holds no usable sample");
std::vector< double > infer_minps(const std::vector< double > &muZ, double nCores, const std::vector< MlpsSample > &samples)
MINPS: run MLPS and RPS and keep whichever gives the smaller mean demand.
std::vector< double > infer_minps_from_trace(const std::vector< MinpsClassTrace > &traces, std::size_t initSample, std::size_t sampleSize, double nCores)
Prepare the trace and run MINPS on it, as the reference's last line does.
MinpsSetup infer_minps_setup(const std::vector< MinpsClassTrace > &traces, std::size_t initSample, std::size_t sampleSize)
Turn a raw per-class trace into the sample set MINPS estimates from.