Refactor: Consistently use smart pointers in test-backend-ops (#25440)

* Use smart pointers in test_case::eval

This makes it consistent with other methods of `test_case`.

* Use smart pointer in show_test_coverage also

* Also use smart pointers for backends
This commit is contained in:
Oliver Simons
2026-07-09 15:00:17 +02:00
committed by GitHub
parent 683f0c72e5
commit f84a519403
+30 -53
View File
@@ -1326,34 +1326,32 @@ struct test_case {
}; };
const bool use_weights = use_weight_context(); const bool use_weights = use_weight_context();
ggml_context * ctx = ggml_init(params); ggml_context_ptr ctx(ggml_init(params));
GGML_ASSERT(ctx); 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); GGML_ASSERT(!use_weights || ctx_weights);
gf = ggml_new_graph(ctx); gf = ggml_new_graph(ctx.get());
// pre-graph sentinel // pre-graph sentinel
add_sentinel(ctx); add_sentinel(ctx.get());
if (ctx_weights) { 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); current_op_name = op_desc(out);
check_for_f16_tensor(ctx); check_for_f16_tensor(ctx.get());
if (!matches_filter(out, op_names_filter)) { if (!matches_filter(out, op_names_filter)) {
//printf(" %s: skipping\n", op_desc(out).c_str()); //printf(" %s: skipping\n", op_desc(out).c_str());
ggml_free(ctx_weights);
ggml_free(ctx);
return test_status_t::SKIPPED; return test_status_t::SKIPPED;
} }
// check if the backends support the ops // check if the backends support the ops
bool supported = true; bool supported = true;
for (ggml_backend_t backend : {backend1, backend2}) { 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)) { if (!ggml_backend_supports_op(backend, t)) {
supported = false; supported = false;
break; break;
@@ -1368,37 +1366,30 @@ struct test_case {
print_test_result_locked(output_printer, result); print_test_result_locked(output_printer, result);
ggml_free(ctx_weights);
ggml_free(ctx);
return test_status_t::NOT_SUPPORTED; return test_status_t::NOT_SUPPORTED;
} }
// post-graph sentinel // post-graph sentinel
add_sentinel(ctx); add_sentinel(ctx.get());
if (ctx_weights) { 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) { 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) { if (buf_weights == NULL) {
printf("failed to allocate weight tensors [%s] ", ggml_backend_name(backend1)); printf("failed to allocate weight tensors [%s] ", ggml_backend_name(backend1));
ggml_free(ctx_weights);
ggml_free(ctx);
return test_status_t::FAIL; 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 // 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) { if (buf == NULL) {
printf("failed to allocate tensors [%s] ", ggml_backend_name(backend1)); 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; return test_status_t::FAIL;
} }
@@ -1411,9 +1402,9 @@ struct test_case {
} }
// randomize tensors // randomize tensors
initialize_tensors(ctx); initialize_tensors(ctx.get());
if (ctx_weights) { if (ctx_weights) {
initialize_tensors(ctx_weights); initialize_tensors(ctx_weights.get());
} }
// compare // compare
@@ -1499,11 +1490,6 @@ struct test_case {
run_whole_graph() ? fused_nodes_to_verify.data() : nullptr, run_whole_graph() ? fused_nodes_to_verify.data() : nullptr,
fused_nodes_to_verify.size()); 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 // Create test result
bool test_passed = ud.ok && cmp_ok; bool test_passed = ud.ok && cmp_ok;
std::string error_msg = test_passed ? "" : (!cmp_ok ? "compare failed" : "test failed"); std::string error_msg = test_passed ? "" : (!cmp_ok ? "compare failed" : "test failed");
@@ -9842,7 +9828,7 @@ static bool test_backend(ggml_backend_t backend, ggml_backend_dev_t dev, test_mo
filter_test_cases(test_cases, params_filter); filter_test_cases(test_cases, params_filter);
if (mode == MODE_TEST) { 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) { if (backend_cpu == NULL) {
test_operation_info info("", "", "CPU"); test_operation_info info("", "", "CPU");
info.set_error("backend", "Failed to initialize CPU backend"); info.set_error("backend", "Failed to initialize CPU backend");
@@ -9851,10 +9837,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 // Use reference implementation on the CPU backend for comparison
using ggml_backend_cpu_set_use_ref_t = void (*)(ggml_backend_t, bool); 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"); 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) { if (set_use_ref) {
set_use_ref(backend_cpu, true); set_use_ref(backend_cpu.get(), true);
} }
std::atomic<size_t> n_ok = 0; std::atomic<size_t> n_ok = 0;
@@ -9901,29 +9887,26 @@ static bool test_backend(ggml_backend_t backend, ggml_backend_dev_t dev, test_mo
if (parallel_workers <= 1) { if (parallel_workers <= 1) {
// Reuse the outer backend / backend_cpu so we don't pay an // Reuse the outer backend / backend_cpu so we don't pay an
// extra CPU backend init. // extra CPU backend init.
run_tests(backend, backend_cpu); run_tests(backend, backend_cpu.get());
} else { } else {
std::atomic<size_t> workers_started = 0; std::atomic<size_t> workers_started = 0;
const auto & eval_worker = [&]() { 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) { if (b == NULL) {
return; 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) { if (b_cpu == NULL) {
ggml_backend_free(b);
return; return;
} }
if (set_use_ref) { if (set_use_ref) {
set_use_ref(b_cpu, true); set_use_ref(b_cpu.get(), true);
} }
workers_started++; workers_started++;
run_tests(b, b_cpu); run_tests(b.get(), b_cpu.get());
ggml_backend_free(b_cpu);
ggml_backend_free(b);
}; };
std::vector<std::thread> threads; std::vector<std::thread> threads;
@@ -9936,7 +9919,6 @@ static bool test_backend(ggml_backend_t backend, ggml_backend_dev_t dev, test_mo
} }
if (workers_started == 0 && !test_cases.empty()) { if (workers_started == 0 && !test_cases.empty()) {
ggml_backend_free(backend_cpu);
return false; return false;
} }
} }
@@ -9944,8 +9926,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_summary(test_summary_info(n_ok, tests_run, false));
output_printer->print_failed_tests(failed_tests); output_printer->print_failed_tests(failed_tests);
ggml_backend_free(backend_cpu);
return n_ok == tests_run; return n_ok == tests_run;
} }
@@ -10051,10 +10031,10 @@ static void show_test_coverage() {
}; };
for (auto & test_case : test_cases) { for (auto & test_case : test_cases) {
ggml_context * ctx = ggml_init(params); ggml_context_ptr ctx(ggml_init(params));
if (ctx) { if (ctx) {
test_case->mode = MODE_TEST; 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 && out->op != GGML_OP_NONE) {
if (out->op == GGML_OP_UNARY) { if (out->op == GGML_OP_UNARY) {
tested_ops.insert(ggml_unary_op_name(ggml_get_unary_op(out))); tested_ops.insert(ggml_unary_op_name(ggml_get_unary_op(out)));
@@ -10064,7 +10044,6 @@ static void show_test_coverage() {
tested_ops.insert(ggml_op_name(out->op)); tested_ops.insert(ggml_op_name(out->op));
} }
} }
ggml_free(ctx);
} }
} }
std::set<std::string> covered_ops; std::set<std::string> covered_ops;
@@ -10219,14 +10198,14 @@ int main(int argc, char ** argv) {
continue; 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_ASSERT(backend != NULL);
ggml_backend_reg_t reg = ggml_backend_dev_backend_reg(dev); 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"); 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) { if (ggml_backend_set_n_threads_fn) {
// TODO: better value for n_threads // 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 size_t free, total; // NOLINT
@@ -10235,15 +10214,13 @@ int main(int argc, char ** argv) {
false, "", ggml_backend_dev_description(dev), false, "", ggml_backend_dev_description(dev),
total / 1024 / 1024, free / 1024 / 1024, true)); 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) { if (ok) {
n_ok++; n_ok++;
} }
output_printer->print_backend_status( output_printer->print_backend_status(
backend_status_info(ggml_backend_name(backend), ok ? test_status_t::OK : test_status_t::FAIL)); backend_status_info(ggml_backend_name(backend.get()), ok ? test_status_t::OK : test_status_t::FAIL));
ggml_backend_free(backend);
} }
ggml_quantize_free(); ggml_quantize_free();