Skip to content

Commit 64bd608

Browse files
danbevwalidbr
authored andcommitted
tests : add --list-ops and --show-coverage options (ggml-org#15745)
This commit adds two new command-line options to the test-backend-ops.cpp that allow users to list all available GGML operations and to show test coverage of these operations. The motivation for this is that it can be useful to quickly see which operations are currently covered by tests and which are not. Also it migth be useful when using the `support` mode.
1 parent a99f4af commit 64bd608

File tree

1 file changed

+92
-1
lines changed

1 file changed

+92
-1
lines changed

tests/test-backend-ops.cpp

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <memory>
3535
#include <random>
3636
#include <regex>
37+
#include <set>
3738
#include <string>
3839
#include <string_view>
3940
#include <thread>
@@ -6741,8 +6742,90 @@ static bool test_backend(ggml_backend_t backend, test_mode mode, const char * op
67416742
GGML_ABORT("fatal error");
67426743
}
67436744

6745+
static void list_all_ops() {
6746+
printf("GGML operations:\n");
6747+
std::set<std::string> all_ops;
6748+
6749+
for (int i = 1; i < GGML_OP_COUNT; i++) {
6750+
all_ops.insert(ggml_op_name((enum ggml_op)i));
6751+
}
6752+
for (int i = 0; i < GGML_UNARY_OP_COUNT; i++) {
6753+
all_ops.insert(ggml_unary_op_name((enum ggml_unary_op)i));
6754+
}
6755+
for (int i = 0; i < GGML_GLU_OP_COUNT; i++) {
6756+
all_ops.insert(ggml_glu_op_name((enum ggml_glu_op)i));
6757+
}
6758+
for (const auto & op : all_ops) {
6759+
printf(" %s\n", op.c_str());
6760+
}
6761+
printf("\nTotal: %zu operations\n", all_ops.size());
6762+
}
6763+
6764+
static void show_test_coverage() {
6765+
std::set<std::string> all_ops;
6766+
for (int i = 1; i < GGML_OP_COUNT; i++) {
6767+
all_ops.insert(ggml_op_name((enum ggml_op)i));
6768+
}
6769+
for (int i = 0; i < GGML_UNARY_OP_COUNT; i++) {
6770+
all_ops.insert(ggml_unary_op_name((enum ggml_unary_op)i));
6771+
}
6772+
for (int i = 0; i < GGML_GLU_OP_COUNT; i++) {
6773+
all_ops.insert(ggml_glu_op_name((enum ggml_glu_op)i));
6774+
}
6775+
auto test_cases = make_test_cases_eval();
6776+
std::set<std::string> tested_ops;
6777+
6778+
ggml_init_params params = {
6779+
/* .mem_size = */ ggml_tensor_overhead()*128 + ggml_graph_overhead(),
6780+
/* .mem_base = */ NULL,
6781+
/* .no_alloc = */ true,
6782+
};
6783+
6784+
for (auto & test_case : test_cases) {
6785+
ggml_context * ctx = ggml_init(params);
6786+
if (ctx) {
6787+
test_case->mode = MODE_TEST;
6788+
ggml_tensor * out = test_case->build_graph(ctx);
6789+
if (out && out->op != GGML_OP_NONE) {
6790+
if (out->op == GGML_OP_UNARY) {
6791+
tested_ops.insert(ggml_unary_op_name(ggml_get_unary_op(out)));
6792+
} else if (out->op == GGML_OP_GLU) {
6793+
tested_ops.insert(ggml_glu_op_name(ggml_get_glu_op(out)));
6794+
} else {
6795+
tested_ops.insert(ggml_op_name(out->op));
6796+
}
6797+
}
6798+
ggml_free(ctx);
6799+
}
6800+
}
6801+
std::set<std::string> covered_ops;
6802+
std::set<std::string> uncovered_ops;
6803+
for (const auto & op : all_ops) {
6804+
if (tested_ops.count(op) > 0) {
6805+
covered_ops.insert(op);
6806+
} else {
6807+
uncovered_ops.insert(op);
6808+
}
6809+
}
6810+
6811+
printf("Operations covered by tests (%zu):\n", covered_ops.size());
6812+
for (const auto & op : covered_ops) {
6813+
printf(" ✓ %s\n", op.c_str());
6814+
}
6815+
printf("\nOperations without tests (%zu):\n", uncovered_ops.size());
6816+
for (const auto & op : uncovered_ops) {
6817+
printf(" ✗ %s\n", op.c_str());
6818+
}
6819+
6820+
printf("\nCoverage Summary:\n");
6821+
printf(" Total operations: %zu\n", all_ops.size());
6822+
printf(" Tested operations: %zu\n", covered_ops.size());
6823+
printf(" Untested operations: %zu\n", uncovered_ops.size());
6824+
printf(" Coverage: %.1f%%\n", (double)covered_ops.size() / all_ops.size() * 100.0);
6825+
}
6826+
67446827
static void usage(char ** argv) {
6745-
printf("Usage: %s [mode] [-o <op,..>] [-b <backend>] [-p <params regex>] [--output <console|sql|csv>]\n", argv[0]);
6828+
printf("Usage: %s [mode] [-o <op,..>] [-b <backend>] [-p <params regex>] [--output <console|sql|csv>] [--list-ops] [--show-coverage]\n", argv[0]);
67466829
printf(" valid modes:\n");
67476830
printf(" - test (default, compare with CPU backend for correctness)\n");
67486831
printf(" - grad (compare gradients from backpropagation with method of finite differences)\n");
@@ -6751,6 +6834,8 @@ static void usage(char ** argv) {
67516834
printf(" op names for -o are as given by ggml_op_desc() (e.g. ADD, MUL_MAT, etc),\n");
67526835
printf(" optionally including the full test case string (e.g. \"ADD(type=f16,ne=[1,1,8,1],nr=[1,1,1,1],nf=1)\")\n");
67536836
printf(" --output specifies output format (default: console, options: console, sql, csv)\n");
6837+
printf(" --list-ops lists all available GGML operations\n");
6838+
printf(" --show-coverage shows test coverage\n");
67546839
}
67556840

67566841
int main(int argc, char ** argv) {
@@ -6800,6 +6885,12 @@ int main(int argc, char ** argv) {
68006885
usage(argv);
68016886
return 1;
68026887
}
6888+
} else if (strcmp(argv[i], "--list-ops") == 0) {
6889+
list_all_ops();
6890+
return 0;
6891+
} else if (strcmp(argv[i], "--show-coverage") == 0) {
6892+
show_test_coverage();
6893+
return 0;
68036894
} else {
68046895
usage(argv);
68056896
return 1;

0 commit comments

Comments
 (0)