| 113 | } |
| 114 | |
| 115 | int main(int argc, char ** argv) { |
| 116 | if (argc < 5) { |
| 117 | fprintf(stderr, "Usage: %s <ref_dir> <prephase_ref_dir> <model_path> <cases_tsv>\n", argv[0]); |
| 118 | return 1; |
| 119 | } |
| 120 | |
| 121 | const std::string ref_dir = argv[1]; |
| 122 | const std::string prephase_ref_dir = argv[2]; |
| 123 | const std::string model_path = argv[3]; |
| 124 | const std::string cases_path = argv[4]; |
| 125 | const std::string cpp_root = ref_dir + "/cpp_out_phase6_metal"; |
| 126 | |
| 127 | auto cases = load_cases(cases_path); |
| 128 | if (cases.empty()) { |
| 129 | fprintf(stderr, "No phase 6 cases loaded from %s\n", cases_path.c_str()); |
| 130 | return 1; |
| 131 | } |
| 132 | |
| 133 | if (!ensure_dir(cpp_root)) { |
| 134 | fprintf(stderr, "Failed to create %s\n", cpp_root.c_str()); |
| 135 | return 1; |
| 136 | } |
| 137 | |
| 138 | sam3_params params; |
| 139 | params.model_path = model_path; |
| 140 | params.n_threads = 1; |
| 141 | params.use_gpu = true; |
| 142 | |
| 143 | auto model = sam3_load_model(params); |
| 144 | if (!model) { |
| 145 | fprintf(stderr, "Failed to load model from %s\n", model_path.c_str()); |
| 146 | return 1; |
| 147 | } |
| 148 | |
| 149 | bool overall_ok = true; |
| 150 | for (const auto & tc : cases) { |
| 151 | fprintf(stderr, "\n=== Metal Phase 6 Case %s ===\n", tc.id.c_str()); |
| 152 | |
| 153 | const std::string case_ref_dir = ref_dir + "/" + tc.id; |
| 154 | const std::string case_cpp_dir = cpp_root + "/" + tc.id; |
| 155 | if (!ensure_dir(case_cpp_dir)) { |
| 156 | fprintf(stderr, "Failed to create %s\n", case_cpp_dir.c_str()); |
| 157 | overall_ok = false; |
| 158 | continue; |
| 159 | } |
| 160 | |
| 161 | if (!sam3_test_dump_phase6_from_ref_inputs(*model, prephase_ref_dir, tc.params, |
| 162 | case_cpp_dir, params.n_threads)) { |
| 163 | fprintf(stderr, " [FAIL] could not run Metal phase 6 dump for %s\n", tc.id.c_str()); |
| 164 | overall_ok = false; |
| 165 | continue; |
| 166 | } |
| 167 | |
| 168 | for (const auto & tensor : tensor_cases()) { |
| 169 | auto ref = load_ref_f32(case_ref_dir + "/" + tensor.name); |
| 170 | auto got = load_ref_f32(case_cpp_dir + "/" + tensor.name); |
| 171 | if (ref.data.empty() || got.data.empty() || ref.numel() != got.numel()) { |
| 172 | fprintf(stderr, " [FAIL] %s missing or shape mismatch\n", tensor.name); |
nothing calls this directly
no test coverage detected