From 716ca4dea89df33f5239d569fefd6e85ea6ec9b2 Mon Sep 17 00:00:00 2001 From: Oliver Simons Date: Wed, 8 Jul 2026 11:48:52 +0200 Subject: [PATCH 1/3] Use smart pointers in test_case::eval This makes it consistent with other methods of `test_case`. --- tests/test-backend-ops.cpp | 46 +++++++++++++------------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/tests/test-backend-ops.cpp b/tests/test-backend-ops.cpp index 0c0aac2bba76..92b1a11ad5ad 100644 --- a/tests/test-backend-ops.cpp +++ b/tests/test-backend-ops.cpp @@ -1326,34 +1326,32 @@ struct test_case { }; const bool use_weights = use_weight_context(); - ggml_context * ctx = ggml_init(params); + ggml_context_ptr ctx(ggml_init(params)); GGML_ASSERT(ctx); - ggml_context * ctx_weights = use_weights ? ggml_init(params) : nullptr; + ggml_context_ptr ctx_weights(use_weights ? ggml_init(params) : nullptr); GGML_ASSERT(!use_weights || ctx_weights); - gf = ggml_new_graph(ctx); + gf = ggml_new_graph(ctx.get()); // pre-graph sentinel - add_sentinel(ctx); + add_sentinel(ctx.get()); if (ctx_weights) { - add_sentinel(ctx_weights); + add_sentinel(ctx_weights.get()); } - ggml_tensor * out = build_graph(ctx, ctx_weights); + ggml_tensor * out = build_graph(ctx.get(), ctx_weights.get()); current_op_name = op_desc(out); - check_for_f16_tensor(ctx); + check_for_f16_tensor(ctx.get()); if (!matches_filter(out, op_names_filter)) { //printf(" %s: skipping\n", op_desc(out).c_str()); - ggml_free(ctx_weights); - ggml_free(ctx); return test_status_t::SKIPPED; } // check if the backends support the ops bool supported = true; for (ggml_backend_t backend : {backend1, backend2}) { - for (ggml_tensor * t = ggml_get_first_tensor(ctx); t != NULL; t = ggml_get_next_tensor(ctx, t)) { + for (ggml_tensor * t = ggml_get_first_tensor(ctx.get()); t != NULL; t = ggml_get_next_tensor(ctx.get(), t)) { if (!ggml_backend_supports_op(backend, t)) { supported = false; break; @@ -1368,37 +1366,30 @@ struct test_case { print_test_result_locked(output_printer, result); - ggml_free(ctx_weights); - ggml_free(ctx); return test_status_t::NOT_SUPPORTED; } // post-graph sentinel - add_sentinel(ctx); + add_sentinel(ctx.get()); if (ctx_weights) { - add_sentinel(ctx_weights); + add_sentinel(ctx_weights.get()); } - ggml_backend_buffer_t buf_weights = nullptr; + ggml_backend_buffer_ptr buf_weights(nullptr); if (ctx_weights) { - buf_weights = ggml_backend_alloc_ctx_tensors(ctx_weights, backend1); + buf_weights.reset(ggml_backend_alloc_ctx_tensors(ctx_weights.get(), backend1)); if (buf_weights == NULL) { printf("failed to allocate weight tensors [%s] ", ggml_backend_name(backend1)); - ggml_free(ctx_weights); - ggml_free(ctx); return test_status_t::FAIL; } - ggml_backend_buffer_set_usage(buf_weights, GGML_BACKEND_BUFFER_USAGE_WEIGHTS); + ggml_backend_buffer_set_usage(buf_weights.get(), GGML_BACKEND_BUFFER_USAGE_WEIGHTS); } // allocate - ggml_backend_buffer_t buf = ggml_backend_alloc_ctx_tensors(ctx, backend1); + ggml_backend_buffer_ptr buf(ggml_backend_alloc_ctx_tensors(ctx.get(), backend1)); if (buf == NULL) { printf("failed to allocate tensors [%s] ", ggml_backend_name(backend1)); - ggml_backend_buffer_free(buf_weights); - ggml_free(ctx_weights); - ggml_free(ctx); return test_status_t::FAIL; } @@ -1411,9 +1402,9 @@ struct test_case { } // randomize tensors - initialize_tensors(ctx); + initialize_tensors(ctx.get()); if (ctx_weights) { - initialize_tensors(ctx_weights); + initialize_tensors(ctx_weights.get()); } // compare @@ -1499,11 +1490,6 @@ struct test_case { run_whole_graph() ? fused_nodes_to_verify.data() : nullptr, fused_nodes_to_verify.size()); - ggml_backend_buffer_free(buf); - ggml_backend_buffer_free(buf_weights); - ggml_free(ctx_weights); - ggml_free(ctx); - // Create test result bool test_passed = ud.ok && cmp_ok; std::string error_msg = test_passed ? "" : (!cmp_ok ? "compare failed" : "test failed"); From 95f7d675f37fff21187423a92a0f32e789906ede Mon Sep 17 00:00:00 2001 From: Oliver Simons Date: Wed, 8 Jul 2026 11:50:59 +0200 Subject: [PATCH 2/3] Use smart pointer in show_test_coverage also --- tests/test-backend-ops.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/test-backend-ops.cpp b/tests/test-backend-ops.cpp index 92b1a11ad5ad..ea828fcade41 100644 --- a/tests/test-backend-ops.cpp +++ b/tests/test-backend-ops.cpp @@ -10025,10 +10025,10 @@ static void show_test_coverage() { }; for (auto & test_case : test_cases) { - ggml_context * ctx = ggml_init(params); + ggml_context_ptr ctx(ggml_init(params)); if (ctx) { test_case->mode = MODE_TEST; - ggml_tensor * out = test_case->build_graph(ctx); + ggml_tensor * out = test_case->build_graph(ctx.get()); if (out && out->op != GGML_OP_NONE) { if (out->op == GGML_OP_UNARY) { tested_ops.insert(ggml_unary_op_name(ggml_get_unary_op(out))); @@ -10038,7 +10038,6 @@ static void show_test_coverage() { tested_ops.insert(ggml_op_name(out->op)); } } - ggml_free(ctx); } } std::set covered_ops; From c6b4db2767a480ad0639692a76622b08a339d8e2 Mon Sep 17 00:00:00 2001 From: Oliver Simons Date: Wed, 8 Jul 2026 11:57:42 +0200 Subject: [PATCH 3/3] Also use smart pointers for backends --- tests/test-backend-ops.cpp | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/tests/test-backend-ops.cpp b/tests/test-backend-ops.cpp index ea828fcade41..000e9c735bd5 100644 --- a/tests/test-backend-ops.cpp +++ b/tests/test-backend-ops.cpp @@ -9816,7 +9816,7 @@ static bool test_backend(ggml_backend_t backend, ggml_backend_dev_t dev, test_mo filter_test_cases(test_cases, params_filter); if (mode == MODE_TEST) { - ggml_backend_t backend_cpu = ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, NULL); + ggml_backend_ptr backend_cpu(ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, NULL)); if (backend_cpu == NULL) { test_operation_info info("", "", "CPU"); info.set_error("backend", "Failed to initialize CPU backend"); @@ -9825,10 +9825,10 @@ static bool test_backend(ggml_backend_t backend, ggml_backend_dev_t dev, test_mo } // Use reference implementation on the CPU backend for comparison using ggml_backend_cpu_set_use_ref_t = void (*)(ggml_backend_t, bool); - auto * reg = ggml_backend_dev_backend_reg(ggml_backend_get_device(backend_cpu)); + auto * reg = ggml_backend_dev_backend_reg(ggml_backend_get_device(backend_cpu.get())); auto * set_use_ref = (ggml_backend_cpu_set_use_ref_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_cpu_set_use_ref"); if (set_use_ref) { - set_use_ref(backend_cpu, true); + set_use_ref(backend_cpu.get(), true); } std::atomic n_ok = 0; @@ -9875,29 +9875,26 @@ static bool test_backend(ggml_backend_t backend, ggml_backend_dev_t dev, test_mo if (parallel_workers <= 1) { // Reuse the outer backend / backend_cpu so we don't pay an // extra CPU backend init. - run_tests(backend, backend_cpu); + run_tests(backend, backend_cpu.get()); } else { std::atomic workers_started = 0; const auto & eval_worker = [&]() { - ggml_backend_t b = ggml_backend_dev_init(dev, NULL); + ggml_backend_ptr b(ggml_backend_dev_init(dev, NULL)); if (b == NULL) { return; } - ggml_backend_t b_cpu = ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, NULL); + ggml_backend_ptr b_cpu(ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, NULL)); if (b_cpu == NULL) { - ggml_backend_free(b); return; } if (set_use_ref) { - set_use_ref(b_cpu, true); + set_use_ref(b_cpu.get(), true); } workers_started++; - run_tests(b, b_cpu); - ggml_backend_free(b_cpu); - ggml_backend_free(b); + run_tests(b.get(), b_cpu.get()); }; std::vector threads; @@ -9910,7 +9907,6 @@ static bool test_backend(ggml_backend_t backend, ggml_backend_dev_t dev, test_mo } if (workers_started == 0 && !test_cases.empty()) { - ggml_backend_free(backend_cpu); return false; } } @@ -9918,8 +9914,6 @@ static bool test_backend(ggml_backend_t backend, ggml_backend_dev_t dev, test_mo output_printer->print_summary(test_summary_info(n_ok, tests_run, false)); output_printer->print_failed_tests(failed_tests); - ggml_backend_free(backend_cpu); - return n_ok == tests_run; } @@ -10192,14 +10186,14 @@ int main(int argc, char ** argv) { continue; } - ggml_backend_t backend = ggml_backend_dev_init(dev, NULL); + ggml_backend_ptr backend(ggml_backend_dev_init(dev, NULL)); GGML_ASSERT(backend != NULL); ggml_backend_reg_t reg = ggml_backend_dev_backend_reg(dev); auto ggml_backend_set_n_threads_fn = (ggml_backend_set_n_threads_t) ggml_backend_reg_get_proc_address(reg, "ggml_backend_set_n_threads"); if (ggml_backend_set_n_threads_fn) { // TODO: better value for n_threads - ggml_backend_set_n_threads_fn(backend, N_THREADS); + ggml_backend_set_n_threads_fn(backend.get(), N_THREADS); } size_t free, total; // NOLINT @@ -10208,15 +10202,13 @@ int main(int argc, char ** argv) { false, "", ggml_backend_dev_description(dev), total / 1024 / 1024, free / 1024 / 1024, true)); - bool ok = test_backend(backend, dev, mode, op_names_filter, params_filter, output_printer.get(), test_file_path, parallel_workers); + bool ok = test_backend(backend.get(), dev, mode, op_names_filter, params_filter, output_printer.get(), test_file_path, parallel_workers); if (ok) { n_ok++; } output_printer->print_backend_status( - backend_status_info(ggml_backend_name(backend), ok ? test_status_t::OK : test_status_t::FAIL)); - - ggml_backend_free(backend); + backend_status_info(ggml_backend_name(backend.get()), ok ? test_status_t::OK : test_status_t::FAIL)); } ggml_quantize_free();