| 248 | } |
| 249 | |
| 250 | static int load_imatrix(const std::string & imatrix_file, std::vector<std::string> & imatrix_datasets, std::unordered_map<std::string, std::vector<float>> & imatrix_data) { |
| 251 | |
| 252 | struct ggml_context * ctx = nullptr; |
| 253 | struct gguf_init_params meta_gguf_params = { |
| 254 | /* .no_alloc = */ false, // the data is needed |
| 255 | /* .ctx = */ &ctx, |
| 256 | }; |
| 257 | struct gguf_context * ctx_gguf = gguf_init_from_file(imatrix_file.c_str(), meta_gguf_params); |
| 258 | if (!ctx_gguf) { |
| 259 | fprintf(stderr, "%s: imatrix file '%s' is using old format\n", __func__, imatrix_file.c_str()); |
| 260 | return load_legacy_imatrix(imatrix_file, imatrix_datasets, imatrix_data); |
| 261 | } |
| 262 | const int32_t n_entries = gguf_get_n_tensors(ctx_gguf); |
| 263 | if (n_entries < 1) { |
| 264 | fprintf(stderr, "%s: no data in file %s\n", __func__, imatrix_file.c_str()); |
| 265 | gguf_free(ctx_gguf); |
| 266 | ggml_free(ctx); |
| 267 | exit(1); |
| 268 | } |
| 269 | |
| 270 | const int dataset_idx = gguf_find_key(ctx_gguf, LLM_KV_IMATRIX_DATASETS); |
| 271 | const int chunk_count_idx = gguf_find_key(ctx_gguf, LLM_KV_IMATRIX_CHUNK_COUNT); |
| 272 | const int chunk_size_idx = gguf_find_key(ctx_gguf, LLM_KV_IMATRIX_CHUNK_SIZE); |
| 273 | if (dataset_idx < 0 || chunk_count_idx < 0 || chunk_size_idx < 0) { |
| 274 | fprintf(stderr, "%s: missing imatrix metadata in file %s\n", __func__, imatrix_file.c_str()); |
| 275 | gguf_free(ctx_gguf); |
| 276 | ggml_free(ctx); |
| 277 | exit(1); |
| 278 | } |
| 279 | |
| 280 | const uint32_t chunk_size = gguf_get_val_u32(ctx_gguf, chunk_size_idx); |
| 281 | |
| 282 | const std::string sums_suffix{ ".in_sum2" }; |
| 283 | const std::string counts_suffix{ ".counts" }; |
| 284 | |
| 285 | // Using an ordered map to get a deterministic iteration order. |
| 286 | std::map<std::string, std::pair<struct ggml_tensor *, struct ggml_tensor *>> sums_counts_for; |
| 287 | |
| 288 | for (struct ggml_tensor * cur = ggml_get_first_tensor(ctx); cur; cur = ggml_get_next_tensor(ctx, cur)) { |
| 289 | std::string name = cur->name; |
| 290 | |
| 291 | if (name.empty()) { continue; } |
| 292 | |
| 293 | if (string_remove_suffix(name, sums_suffix)) { |
| 294 | // in_sum2 |
| 295 | sums_counts_for[std::move(name)].first = cur; |
| 296 | } else if (string_remove_suffix(name, counts_suffix)) { |
| 297 | // counts |
| 298 | sums_counts_for[std::move(name)].second = cur; |
| 299 | } else { |
| 300 | // ignore other tensors |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | for (const auto & sc : sums_counts_for) { |
| 305 | const std::string & name = sc.first; |
| 306 | const struct ggml_tensor * sums = sc.second.first; |
| 307 | const struct ggml_tensor * counts = sc.second.second; |
no test coverage detected