| 16 | #include <vector> |
| 17 | |
| 18 | static double run_graph(ggml_backend_t backend, ggml_context* ctx, ggml_cgraph* graph, |
| 19 | const std::vector<ggml_tensor*>& inputs, int warmup, int repeats) { |
| 20 | auto* galloc = ggml_gallocr_new(ggml_backend_get_default_buffer_type(backend)); |
| 21 | if (!ggml_gallocr_reserve(galloc, graph) || !ggml_gallocr_alloc_graph(galloc, graph)) { |
| 22 | fprintf(stderr, "FAIL: alloc\n"); |
| 23 | ggml_gallocr_free(galloc); |
| 24 | return -1; |
| 25 | } |
| 26 | for (auto* t : inputs) { |
| 27 | int64_t nel = ggml_nelements(t); |
| 28 | if (t->type == GGML_TYPE_F32) { |
| 29 | std::vector<float> d(nel, 0.1f); |
| 30 | ggml_backend_tensor_set(t, d.data(), 0, nel * sizeof(float)); |
| 31 | } else if (t->type == GGML_TYPE_F16) { |
| 32 | std::vector<uint16_t> d(nel); |
| 33 | for (int64_t j = 0; j < nel; j++) d[j] = ggml_fp32_to_fp16(0.1f); |
| 34 | ggml_backend_tensor_set(t, d.data(), 0, nel * sizeof(uint16_t)); |
| 35 | } |
| 36 | } |
| 37 | if (ggml_backend_is_cpu(backend)) |
| 38 | ggml_backend_cpu_set_n_threads(backend, 8); |
| 39 | |
| 40 | for (int i = 0; i < warmup; i++) |
| 41 | ggml_backend_graph_compute(backend, graph); |
| 42 | auto t0 = std::chrono::high_resolution_clock::now(); |
| 43 | for (int i = 0; i < repeats; i++) |
| 44 | ggml_backend_graph_compute(backend, graph); |
| 45 | auto t1 = std::chrono::high_resolution_clock::now(); |
| 46 | ggml_gallocr_free(galloc); |
| 47 | return std::chrono::duration<double, std::milli>(t1 - t0).count() / repeats; |
| 48 | } |
| 49 | |
| 50 | // ═══════════════════════════════════════════════════════════════════════════════ |
| 51 | // TEST 1: Pure dispatch overhead — chain of N trivial add ops |
no outgoing calls
no test coverage detected