@@ -218,20 +218,62 @@ void IMatrixCollector::save_imatrix(int ncall) const {
218
218
fname += std::to_string (ncall);
219
219
}
220
220
221
+ // avoid writing imatrix entries that do not have full data
222
+ // this can happen with MoE models where some of the experts end up not being exercised by the provided training data
223
+
224
+ int n_entries = 0 ;
225
+ std::vector<std::string> to_store;
226
+
227
+ bool is_first = true ; // for printing
228
+ for (const auto & kv : m_stats) {
229
+ if (kv.second .counts .empty ()) {
230
+ continue ;
231
+ }
232
+
233
+ int n_zeros = 0 ;
234
+ for (const int c : kv.second .counts ) {
235
+ if (c == 0 ) {
236
+ n_zeros++;
237
+ }
238
+ }
239
+
240
+ if (n_zeros != 0 && is_first) {
241
+ fprintf (stderr, " \n " );
242
+ is_first = false ;
243
+ }
244
+
245
+ if (n_zeros == (int )kv.second .counts .size ()) {
246
+ fprintf (stderr, " %s: entry '%40s' has no data - skipping\n " , __func__, kv.first .c_str ());
247
+ continue ;
248
+ }
249
+
250
+ if (n_zeros > 0 ) {
251
+ fprintf (stderr, " %s: entry '%40s' has partial data (%.2f%%) - skipping\n " , __func__, kv.first .c_str (), 100 .0f * (kv.second .counts .size () - n_zeros) / kv.second .counts .size ());
252
+ continue ;
253
+ }
254
+
255
+ n_entries++;
256
+ to_store.push_back (kv.first );
257
+ }
258
+
259
+ if (to_store.size () < m_stats.size ()) {
260
+ fprintf (stderr, " %s: warning: storing only %zu out of %zu entries\n " , __func__, to_store.size (), m_stats.size ());
261
+ }
262
+
221
263
std::ofstream out (fname, std::ios::binary);
222
- int n_entries = m_stats.size ();
223
264
out.write ((const char *) &n_entries, sizeof (n_entries));
224
- for (const auto & p : m_stats) {
225
- int len = p.first .size ();
265
+ for (const auto & name : to_store) {
266
+ const auto & stat = m_stats.at (name);
267
+ int len = name.size ();
226
268
out.write ((const char *) &len, sizeof (len));
227
- out.write (p. first .c_str (), len);
228
- out.write ((const char *) &p. second . ncall , sizeof (p. second .ncall ));
229
- int nval = p. second .values .size ();
269
+ out.write (name .c_str (), len);
270
+ out.write ((const char *) &stat. ncall , sizeof (stat .ncall ));
271
+ int nval = stat .values .size ();
230
272
out.write ((const char *) &nval, sizeof (nval));
231
273
if (nval > 0 ) {
232
274
std::vector<float > tmp (nval);
233
275
for (int i = 0 ; i < nval; i++) {
234
- tmp[i] = (p. second . values [i] / static_cast <float >(p. second . counts [i])) * static_cast <float >(p. second .ncall );
276
+ tmp[i] = (stat. values [i] / static_cast <float >(stat. counts [i])) * static_cast <float >(stat .ncall );
235
277
}
236
278
out.write ((const char *)tmp.data (), nval*sizeof (float ));
237
279
}
0 commit comments