| 320 | } |
| 321 | |
| 322 | static void ggml_opt_build(ggml_opt_context_t opt_ctx) { |
| 323 | GGML_ASSERT(opt_ctx->ctx_compute && "no compute context set, either use static graphs or set one with ggml_opt_prepare_alloc"); |
| 324 | GGML_ASSERT((!opt_ctx->static_graphs || opt_ctx->inputs->data) && "when using static graphs the inputs must be allocated statically"); |
| 325 | |
| 326 | const enum ggml_opt_optimizer_type optimizer = opt_ctx->optimizer; |
| 327 | |
| 328 | const bool accumulate = opt_ctx->build_type_alloc >= GGML_OPT_BUILD_TYPE_GRAD && |
| 329 | !(opt_ctx->static_graphs && opt_ctx->build_type_alloc == GGML_OPT_BUILD_TYPE_OPT && opt_ctx->opt_period == 1); |
| 330 | |
| 331 | const bool need_momenta = opt_ctx->build_type_alloc == GGML_OPT_BUILD_TYPE_OPT && |
| 332 | opt_ctx->optimizer == GGML_OPT_OPTIMIZER_TYPE_ADAMW; |
| 333 | |
| 334 | ggml_set_input(opt_ctx->inputs); |
| 335 | ggml_set_output(opt_ctx->outputs); |
| 336 | |
| 337 | int n_param = 0; |
| 338 | for (int i = 0; i < opt_ctx->gf->n_nodes; ++i) { |
| 339 | const struct ggml_tensor * node = opt_ctx->gf->nodes[i]; |
| 340 | if (node->flags & GGML_TENSOR_FLAG_PARAM) { |
| 341 | n_param++; |
| 342 | } |
| 343 | GGML_ASSERT(!(node->flags & GGML_TENSOR_FLAG_LOSS) && "support for extra loss terms not implemented"); |
| 344 | } |
| 345 | |
| 346 | if (!opt_ctx->ctx_static) { |
| 347 | // The static context is used for: |
| 348 | // - gradients (1 per loss, 1 tensor per param if using gradient accumulation) |
| 349 | // - optimizer momenta (2 tensors per param) |
| 350 | // - labels (if using static graphs) |
| 351 | // - loss (if using static graphs, up to 5 tensors) |
| 352 | // - pred (if using static graphs) |
| 353 | // - ncorrect (if using static graphs, 2 tensors). |
| 354 | constexpr size_t n_loss = 1; |
| 355 | const size_t tensors_per_param = (accumulate ? 1 : 0) + (need_momenta ? 2 : 0); |
| 356 | const size_t tensors_const = opt_ctx->static_graphs ? 9 : 0; |
| 357 | const size_t size_meta = (n_loss + tensors_per_param*n_param + tensors_const) * ggml_tensor_overhead(); |
| 358 | struct ggml_init_params params = { |
| 359 | /*.mem_size =*/ size_meta, |
| 360 | /*.mem_buffer =*/ nullptr, |
| 361 | /*.no_alloc =*/ true, |
| 362 | }; |
| 363 | opt_ctx->ctx_static = ggml_init(params); |
| 364 | } |
| 365 | GGML_ASSERT(opt_ctx->build_type <= opt_ctx->build_type_alloc); |
| 366 | |
| 367 | { |
| 368 | // The cpu context is allocated statically if using static graphs, dynamically otherwise. |
| 369 | // It is used for: |
| 370 | // - optimizer parameters (1 shared for all optimizer invocations) |
| 371 | const size_t size_meta = 1 * ggml_tensor_overhead(); |
| 372 | struct ggml_init_params params = { |
| 373 | /*.mem_size =*/ size_meta, |
| 374 | /*.mem_buffer =*/ nullptr, |
| 375 | /*.no_alloc =*/ true, |
| 376 | }; |
| 377 | ggml_free(opt_ctx->ctx_cpu); |
| 378 | opt_ctx->ctx_cpu = ggml_init(params); |
| 379 |
no test coverage detected