| 218 | } |
| 219 | |
| 220 | 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) { |
| 221 | |
| 222 | struct ggml_context * ctx = nullptr; |
| 223 | struct gguf_init_params meta_gguf_params = { |
| 224 | /* .no_alloc = */ false, // the data is needed |
| 225 | /* .ctx = */ &ctx, |
| 226 | }; |
| 227 | struct gguf_context * ctx_gguf = gguf_init_from_file(imatrix_file.c_str(), meta_gguf_params); |
| 228 | if (!ctx_gguf) { |
| 229 | fprintf(stderr, "%s: imatrix file '%s' is using old format\n", __func__, imatrix_file.c_str()); |
| 230 | return load_legacy_imatrix(imatrix_file, imatrix_datasets, imatrix_data); |
| 231 | } |
| 232 | const int32_t n_entries = gguf_get_n_tensors(ctx_gguf); |
| 233 | if (n_entries < 1) { |
| 234 | fprintf(stderr, "%s: no data in file %s\n", __func__, imatrix_file.c_str()); |
| 235 | gguf_free(ctx_gguf); |
| 236 | ggml_free(ctx); |
| 237 | exit(1); |
| 238 | } |
| 239 | |
| 240 | const int dataset_idx = gguf_find_key(ctx_gguf, LLM_KV_IMATRIX_DATASETS); |
| 241 | const int chunk_count_idx = gguf_find_key(ctx_gguf, LLM_KV_IMATRIX_CHUNK_COUNT); |
| 242 | const int chunk_size_idx = gguf_find_key(ctx_gguf, LLM_KV_IMATRIX_CHUNK_SIZE); |
| 243 | if (dataset_idx < 0 || chunk_count_idx < 0 || chunk_size_idx < 0) { |
| 244 | fprintf(stderr, "%s: missing imatrix metadata in file %s\n", __func__, imatrix_file.c_str()); |
| 245 | gguf_free(ctx_gguf); |
| 246 | ggml_free(ctx); |
| 247 | exit(1); |
| 248 | } |
| 249 | |
| 250 | const uint32_t chunk_size = gguf_get_val_u32(ctx_gguf, chunk_size_idx); |
| 251 | |
| 252 | const std::string sums_suffix{ ".in_sum2" }; |
| 253 | const std::string counts_suffix{ ".counts" }; |
| 254 | |
| 255 | // Using an ordered map to get a deterministic iteration order. |
| 256 | std::map<std::string, std::pair<struct ggml_tensor *, struct ggml_tensor *>> sums_counts_for; |
| 257 | |
| 258 | for (struct ggml_tensor * cur = ggml_get_first_tensor(ctx); cur; cur = ggml_get_next_tensor(ctx, cur)) { |
| 259 | std::string name = cur->name; |
| 260 | |
| 261 | if (name.empty()) { continue; } |
| 262 | |
| 263 | if (string_remove_suffix(name, sums_suffix)) { |
| 264 | // in_sum2 |
| 265 | sums_counts_for[std::move(name)].first = cur; |
| 266 | } else if (string_remove_suffix(name, counts_suffix)) { |
| 267 | // counts |
| 268 | sums_counts_for[std::move(name)].second = cur; |
| 269 | } else { |
| 270 | // ignore other tensors |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | for (const auto & sc : sums_counts_for) { |
| 275 | const std::string & name = sc.first; |
| 276 | const struct ggml_tensor * sums = sc.second.first; |
| 277 | const struct ggml_tensor * counts = sc.second.second; |
no test coverage detected