| 15320 | } |
| 15321 | |
| 15322 | void ggml_build_backward_gradient_checkpointing( |
| 15323 | struct ggml_context * ctx, |
| 15324 | struct ggml_cgraph * gf, |
| 15325 | struct ggml_cgraph * gb, |
| 15326 | struct ggml_cgraph * gb_tmp, |
| 15327 | struct ggml_tensor * * checkpoints, |
| 15328 | int n_checkpoints) { |
| 15329 | ggml_graph_cpy(gf, gb_tmp); |
| 15330 | ggml_build_backward_expand(ctx, gf, gb_tmp, true); |
| 15331 | |
| 15332 | if (n_checkpoints <= 0) { |
| 15333 | ggml_graph_cpy(gb_tmp, gb); |
| 15334 | return; |
| 15335 | } |
| 15336 | |
| 15337 | struct hash_map * replacements = ggml_new_hash_map(gf->n_nodes + gf->n_leafs + n_checkpoints); |
| 15338 | |
| 15339 | // insert checkpoints in replacements |
| 15340 | for (int i = 0; i < n_checkpoints; ++i) { |
| 15341 | size_t k = ggml_hash_find(replacements->set, checkpoints[i]); |
| 15342 | GGML_ASSERT(k != GGML_HASHTABLE_FULL); // assert that not full |
| 15343 | GGML_ASSERT(replacements->set.keys[k] == NULL); // assert that we don't overwrite |
| 15344 | replacements->set.keys[k] = checkpoints[i]; |
| 15345 | replacements->vals[k] = checkpoints[i]; |
| 15346 | } |
| 15347 | |
| 15348 | ggml_graph_cpy(gf, gb); |
| 15349 | // rewrite gb_tmp->nodes[gf->n_nodes:gb_tmp->n_nodes], |
| 15350 | // replacing references to gb_tmp->nodes[0:gf->n_nodes] ( == gf->nodes[0:gf->n_nodes]), |
| 15351 | // by recomputing them from checkpoints |
| 15352 | for (int i = gf->n_nodes; i<gb_tmp->n_nodes; ++i) { |
| 15353 | struct ggml_tensor * node = gb_tmp->nodes[i]; |
| 15354 | for (int k = 0; k < GGML_MAX_SRC; ++k) { |
| 15355 | // insert new tensors recomputing src, reusing already made replacements, |
| 15356 | // remember replacements: remember new tensors with mapping from corresponding gf nodes |
| 15357 | // recurse for input tensors, |
| 15358 | // unless (i.e. terminating when) input tensors are replacments (like checkpoints) |
| 15359 | node->src[k] = ggml_recompute_graph_node(ctx, gf, replacements, node->src[k]); |
| 15360 | } |
| 15361 | // insert rewritten backward node with replacements made into resulting backward graph gb |
| 15362 | ggml_build_forward_expand(gb, node); |
| 15363 | } |
| 15364 | |
| 15365 | ggml_hash_map_free(replacements); |
| 15366 | } |
| 15367 | |
| 15368 | // functions to change gradients considering the case that input a might be initial gradient with zero value |
| 15369 |
no test coverage detected