| 217 | } |
| 218 | |
| 219 | bool IMatrixCollector::collect_imatrix(struct ggml_tensor * t, bool ask, void * user_data) { |
| 220 | GGML_UNUSED(user_data); |
| 221 | |
| 222 | const struct ggml_tensor * src0 = t->src[0]; |
| 223 | const struct ggml_tensor * src1 = t->src[1]; |
| 224 | std::string wname = filter_tensor_name(src0->name); |
| 225 | |
| 226 | const int32_t chunk_size = m_params.n_ctx / m_params.n_parallel; |
| 227 | |
| 228 | // when ask is true, the scheduler wants to know if we are interested in data from this tensor |
| 229 | // if we return true, a follow-up call will be made with ask=false in which we can do the actual collection |
| 230 | if (ask) { |
| 231 | if (t->op == GGML_OP_MUL_MAT_ID) return true; // collect all indirect matrix multiplications |
| 232 | if (t->op != GGML_OP_MUL_MAT) return false; |
| 233 | // why are small batches ignored (<16 tokens)? |
| 234 | if (src1->ne[1] < 16 || src1->type != GGML_TYPE_F32) return false; |
| 235 | if (!(wname.substr(0, 4) == "blk." || (m_params.process_output && wname == "output.weight"))) return false; |
| 236 | return true; |
| 237 | } |
| 238 | |
| 239 | std::lock_guard<std::mutex> lock(m_mutex); |
| 240 | |
| 241 | // copy the data from the GPU memory if needed |
| 242 | const bool is_host = ggml_backend_buffer_is_host(src1->buffer); |
| 243 | |
| 244 | if (!is_host) { |
| 245 | const size_t src1_nbytes = ggml_nbytes(src1); |
| 246 | m_src1_data.resize(src1_nbytes); |
| 247 | ggml_backend_tensor_get(src1, m_src1_data.data(), 0, src1_nbytes); |
| 248 | } |
| 249 | |
| 250 | const char * data = is_host ? (const char *) src1->data : m_src1_data.data(); |
| 251 | GGML_ASSERT(src1->nb[0] == ggml_element_size(src1)); |
| 252 | |
| 253 | // this has been adapted to the new format of storing merged experts in a single 3d tensor |
| 254 | // ref: https://github.com/ggml-org/llama.cpp/pull/6387 |
| 255 | if (t->op == GGML_OP_MUL_MAT_ID) { |
| 256 | // ids -> [n_experts_used, n_tokens] |
| 257 | // src1 -> [cols, n_expert_used, n_tokens] |
| 258 | const ggml_tensor * ids = t->src[2]; |
| 259 | const int64_t n_as = src0->ne[2]; |
| 260 | const int64_t n_ids = ids->ne[0]; |
| 261 | |
| 262 | // the top-k selected expert ids are stored in the ids tensor |
| 263 | // for simplicity, always copy ids to host, because it is small |
| 264 | // take into account that ids is not contiguous! |
| 265 | |
| 266 | GGML_ASSERT(ids->ne[1] == src1->ne[2]); |
| 267 | |
| 268 | // the extra dimension would need to be stored somewhere to be reflected in the imatrix file |
| 269 | if (ggml_nrows(src1) != src1->ne[1] * src1->ne[2]) { |
| 270 | LOG_ERR("%s: tensor has more than 3 dimensions: %s", __func__, wname.c_str()); |
| 271 | GGML_ASSERT(false); |
| 272 | } |
| 273 | |
| 274 | m_ids.resize(ggml_nbytes(ids)); |
| 275 | ggml_backend_tensor_get(ids, m_ids.data(), 0, ggml_nbytes(ids)); |
| 276 |
no test coverage detected