39
39
#include < string_view>
40
40
#include < thread>
41
41
#include < vector>
42
+ #include < unordered_map>
42
43
43
44
static void init_tensor_uniform (ggml_tensor * tensor, float min = -1 .0f , float max = 1 .0f ) {
44
45
size_t nels = ggml_nelements (tensor);
@@ -324,6 +325,7 @@ enum test_mode {
324
325
MODE_PERF,
325
326
MODE_GRAD,
326
327
MODE_SUPPORT,
328
+ MODE_CPU_VARIANTS,
327
329
};
328
330
329
331
// Output format support similar to llama-bench
@@ -6880,18 +6882,99 @@ static void show_test_coverage() {
6880
6882
printf (" Coverage: %.1f%%\n " , (double )covered_ops.size () / all_ops.size () * 100.0 );
6881
6883
}
6882
6884
6885
+ static bool test_cpu_variant (const char * variant_name, const char * op_names_filter,
6886
+ const char * params_filter, printer * output_printer) {
6887
+
6888
+ ggml_backend_t backend_ref = ggml_backend_init_by_name (" CPU-ref" , nullptr );
6889
+ if (backend_ref == nullptr ) {
6890
+ printf (" Error: CPU-ref backend not found. Make sure it's built and available.\n " );
6891
+ return false ;
6892
+ }
6893
+
6894
+ ggml_backend_t backend_variant = ggml_backend_init_by_name (variant_name, nullptr );
6895
+ if (backend_variant == nullptr ) {
6896
+ printf (" Error: CPU variant '%s' not found or failed to initialize.\n " , variant_name);
6897
+ printf (" Use --list to see available variants.\n " );
6898
+ ggml_backend_free (backend_ref);
6899
+ return false ;
6900
+ }
6901
+
6902
+ printf (" Testing CPU variant '%s' against cpu-ref backend...\n\n " , variant_name);
6903
+
6904
+ auto test_cases = make_test_cases_eval ();
6905
+
6906
+ if (params_filter != nullptr ) {
6907
+ std::regex regex (params_filter);
6908
+ auto it = test_cases.begin ();
6909
+ while (it != test_cases.end ()) {
6910
+ std::string test_params = (*it)->vars ();
6911
+ if (!std::regex_search (test_params, regex)) {
6912
+ it = test_cases.erase (it);
6913
+ } else {
6914
+ it++;
6915
+ }
6916
+ }
6917
+ }
6918
+
6919
+ size_t n_ok = 0 ;
6920
+ for (auto & test : test_cases) {
6921
+ if (test->eval (backend_variant, backend_ref, op_names_filter, output_printer)) {
6922
+ n_ok++;
6923
+ }
6924
+ }
6925
+
6926
+ output_printer->print_summary (test_summary_info (n_ok, test_cases.size (), false ));
6927
+
6928
+ ggml_backend_free (backend_variant);
6929
+ ggml_backend_free (backend_ref);
6930
+
6931
+ return n_ok == test_cases.size ();
6932
+ }
6933
+
6934
+ static void list_cpu_variants () {
6935
+ std::unordered_map<std::string, std::string> variant_names;
6936
+ for (size_t i = 0 ; i < ggml_backend_reg_count (); i++) {
6937
+ ggml_backend_reg_t reg = ggml_backend_reg_get (i);
6938
+ if (strstr (ggml_backend_reg_name (reg), " CPU" ) != nullptr ) {
6939
+ for (size_t j = 0 ; j < ggml_backend_reg_dev_count (reg); j++) {
6940
+ ggml_backend_dev_t dev = ggml_backend_reg_dev_get (reg, j);
6941
+ const char * name = ggml_backend_dev_name (dev);
6942
+ if (strcmp (name, " CPU-ref" ) != 0 ) {
6943
+ variant_names.emplace (name, ggml_backend_dev_description (dev));
6944
+ }
6945
+ }
6946
+ }
6947
+ }
6948
+
6949
+ if (variant_names.size () == 0 ) {
6950
+ printf (" No CPU backend variants found. To enable CPU variants, rebuild with:\n " );
6951
+ printf (" cmake -DGGML_BACKEND_DL=ON -DGGML_CPU_ALL_VARIANTS=ON\n " );
6952
+ return ;
6953
+ }
6954
+
6955
+ printf (" CPU variants:\n " );
6956
+ for (const auto & it : variant_names) {
6957
+ printf (" %-15s - %s\n " , it.first .c_str (), it.second .c_str ());
6958
+ }
6959
+ }
6960
+
6883
6961
static void usage (char ** argv) {
6884
- printf (" Usage: %s [mode] [-o <op,..>] [-b <backend>] [-p <params regex>] [--output <console|sql|csv>] [--list-ops] [--show-coverage]\n " , argv[0 ]);
6962
+ printf (" Usage: %s [mode] [-o <op,..>] [-b <backend>] [-p <params regex>] [--output <console|sql|csv>] [--list-ops] [--list-cpu-variants] [-- show-coverage]\n " , argv[0 ]);
6885
6963
printf (" valid modes:\n " );
6886
6964
printf (" - test (default, compare with CPU backend for correctness)\n " );
6887
6965
printf (" - grad (compare gradients from backpropagation with method of finite differences)\n " );
6888
6966
printf (" - perf (performance evaluation)\n " );
6889
6967
printf (" - support (probe backend operation support)\n " );
6968
+ printf (" - cpu-variants (test CPU variants against cpu-ref backend)\n " );
6890
6969
printf (" op names for -o are as given by ggml_op_desc() (e.g. ADD, MUL_MAT, etc),\n " );
6891
6970
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 " );
6892
6971
printf (" --output specifies output format (default: console, options: console, sql, csv)\n " );
6893
6972
printf (" --list-ops lists all available GGML operations\n " );
6973
+ printf (" --list-cpu-variants lists all available CPU backend variants\n " );
6894
6974
printf (" --show-coverage shows test coverage\n " );
6975
+ printf (" cpu-variants mode options:\n " );
6976
+ printf (" --list lists available CPU variants on this system\n " );
6977
+ printf (" --variant <name> test specific CPU variant against cpu-ref backend\n " );
6895
6978
}
6896
6979
6897
6980
int main (int argc, char ** argv) {
@@ -6900,6 +6983,8 @@ int main(int argc, char ** argv) {
6900
6983
const char * op_names_filter = nullptr ;
6901
6984
const char * backend_filter = nullptr ;
6902
6985
const char * params_filter = nullptr ;
6986
+ const char * cpu_variant_name = nullptr ;
6987
+ bool list_variants_flag = false ;
6903
6988
6904
6989
for (int i = 1 ; i < argc; i++) {
6905
6990
if (strcmp (argv[i], " test" ) == 0 ) {
@@ -6910,6 +6995,8 @@ int main(int argc, char ** argv) {
6910
6995
mode = MODE_GRAD;
6911
6996
} else if (strcmp (argv[i], " support" ) == 0 ) {
6912
6997
mode = MODE_SUPPORT;
6998
+ } else if (strcmp (argv[i], " cpu-variants" ) == 0 ) {
6999
+ mode = MODE_CPU_VARIANTS;
6913
7000
} else if (strcmp (argv[i], " -o" ) == 0 ) {
6914
7001
if (i + 1 < argc) {
6915
7002
op_names_filter = argv[++i];
@@ -6944,6 +7031,15 @@ int main(int argc, char ** argv) {
6944
7031
} else if (strcmp (argv[i], " --list-ops" ) == 0 ) {
6945
7032
list_all_ops ();
6946
7033
return 0 ;
7034
+ } else if (strcmp (argv[i], " --list" ) == 0 ) {
7035
+ list_variants_flag = true ;
7036
+ } else if (strcmp (argv[i], " --variant" ) == 0 ) {
7037
+ if (i + 1 < argc) {
7038
+ cpu_variant_name = argv[++i];
7039
+ } else {
7040
+ usage (argv);
7041
+ return 1 ;
7042
+ }
6947
7043
} else if (strcmp (argv[i], " --show-coverage" ) == 0 ) {
6948
7044
show_test_coverage ();
6949
7045
return 0 ;
@@ -6962,6 +7058,21 @@ int main(int argc, char ** argv) {
6962
7058
output_printer->print_header ();
6963
7059
}
6964
7060
7061
+ if (mode == MODE_CPU_VARIANTS) {
7062
+ if (list_variants_flag) {
7063
+ list_cpu_variants ();
7064
+ return 0 ;
7065
+ }
7066
+
7067
+ if (cpu_variant_name == nullptr ) {
7068
+ printf (" Error: cpu-variants mode requires --variant <name> or --list\n " );
7069
+ usage (argv);
7070
+ return 1 ;
7071
+ }
7072
+
7073
+ return test_cpu_variant (cpu_variant_name, op_names_filter, params_filter, output_printer.get ()) ? 0 : 1 ;
7074
+ }
7075
+
6965
7076
output_printer->print_testing_start (testing_start_info (ggml_backend_dev_count ()));
6966
7077
6967
7078
size_t n_ok = 0 ;
0 commit comments