|
18 | 18 |
|
19 | 19 | MAX_ACCURACY_LOG_SIZE = 10 * 1024 |
20 | 20 | VIEWABLE_SIZE = 4096 |
21 | | -RESPONSES_LIMIT = 10 * 1024 # cap on truncated responses bytes |
22 | 21 |
|
23 | 22 | HELP_TEXT = """ |
24 | 23 | You can run this tool in 2 ways: |
@@ -124,84 +123,18 @@ def copy_submission_dir(src, dst, filter_submitter): |
124 | 123 | ) |
125 | 124 |
|
126 | 125 |
|
127 | | -def _truncate_endpoints_results(results_path, acc_path, backup): |
128 | | - """Truncate the ``responses`` field in an endpoints accuracy results.json. |
| 126 | +def _is_endpoints_submission(scenario_dir): |
| 127 | + """Detect the endpoints submission layout via its scenario-root config.yaml. |
129 | 128 |
|
130 | | - Mirrors the behaviour of truncate_accuracy_log.py for traditional |
131 | | - submissions: backs up the original file (when --backup is given), |
132 | | - computes a SHA-256 hash of the original, appends ``hash=<hex>`` to |
133 | | - accuracy.txt, then writes back a copy with responses capped at |
134 | | - RESPONSES_LIMIT bytes. |
| 129 | + Endpoints submissions have no mlperf_log_accuracy.json; the accuracy |
| 130 | + artifact they produce (accuracy/accuracy_results.json) carries no large |
| 131 | + per-sample payload to truncate, so callers should skip truncation |
| 132 | + entirely rather than look for a file to shrink. |
135 | 133 | """ |
136 | | - try: |
137 | | - with open(results_path, "r", encoding="utf-8") as f: |
138 | | - original_bytes = f.read().encode() |
139 | | - data = json.loads(original_bytes) |
140 | | - except Exception as exc: |
141 | | - log.error("Could not read %s: %s", results_path, exc) |
142 | | - return |
143 | | - |
144 | | - # Back up before any modification. |
145 | | - if backup: |
146 | | - backup_dir = os.path.join(backup, acc_path) |
147 | | - os.makedirs(backup_dir, exist_ok=True) |
148 | | - dst = os.path.join(backup_dir, "results.json") |
149 | | - if os.path.exists(dst): |
150 | | - log.error( |
151 | | - "not processing %s because %s already exists", |
152 | | - results_path, |
153 | | - dst, |
154 | | - ) |
155 | | - return |
156 | | - shutil.copy(results_path, dst) |
157 | | - |
158 | | - # Hash the original file for audit purposes (mirrors accuracy.txt hash |
159 | | - # written for traditional mlperf_log_accuracy.json truncation). |
160 | | - hash_val = hashlib.sha256(original_bytes).hexdigest() |
161 | | - acc_txt = os.path.join(acc_path, "accuracy.txt") |
162 | | - with open(acc_txt, "a", encoding="utf-8") as f: |
163 | | - f.write("\nhash={0}\n".format(hash_val)) |
164 | | - |
165 | | - # Truncate the responses collection so the file stays small. |
166 | | - responses = data.get("responses") |
167 | | - if responses is None or (isinstance( |
168 | | - responses, (list, dict)) and not responses): |
169 | | - log.info("%s has no responses to truncate", results_path) |
170 | | - return |
171 | | - |
172 | | - if isinstance(responses, list): |
173 | | - total = 2 # "[]" |
174 | | - idx = 0 |
175 | | - for i, r in enumerate(responses): |
176 | | - total += len(json.dumps(r).encode()) + (2 if i > 0 else 0) |
177 | | - if total > RESPONSES_LIMIT: |
178 | | - break |
179 | | - idx = i + 1 |
180 | | - data["responses"] = responses[:idx] |
181 | | - elif isinstance(responses, dict): |
182 | | - total = 2 # "{}" |
183 | | - kept = {} |
184 | | - for i, (k, v) in enumerate(responses.items()): |
185 | | - entry = len(json.dumps(k).encode()) + \ |
186 | | - len(json.dumps(v).encode()) + 2 |
187 | | - if i > 0: |
188 | | - entry += 2 |
189 | | - if total + entry > RESPONSES_LIMIT: |
190 | | - break |
191 | | - total += entry |
192 | | - kept[k] = v |
193 | | - data["responses"] = kept |
194 | | - else: |
195 | | - log.error( |
196 | | - "%s: responses has unexpected type %s; skipping truncation", |
197 | | - results_path, |
198 | | - type(responses).__name__, |
199 | | - ) |
200 | | - return |
201 | | - |
202 | | - with open(results_path, "w", encoding="utf-8") as f: |
203 | | - json.dump(data, f, indent=2) |
204 | | - log.info("%s responses truncated", results_path) |
| 134 | + return any( |
| 135 | + os.path.exists(os.path.join(scenario_dir, name)) |
| 136 | + for name in ("config.yaml", "config.yml") |
| 137 | + ) |
205 | 138 |
|
206 | 139 |
|
207 | 140 | def truncate_results_dir(filter_submitter, backup, scenarios_to_skip): |
@@ -264,14 +197,10 @@ def truncate_results_dir(filter_submitter, backup, scenarios_to_skip): |
264 | 197 | acc_txt = os.path.join( |
265 | 198 | acc_path, "accuracy.txt") |
266 | 199 | if not os.path.exists(acc_log): |
267 | | - # Endpoints submissions have results.json |
268 | | - # instead of mlperf_log_accuracy.json |
269 | | - endpoints_results = os.path.join( |
270 | | - acc_path, "results.json" |
271 | | - ) |
272 | | - if os.path.exists(endpoints_results): |
273 | | - _truncate_endpoints_results( |
274 | | - endpoints_results, acc_path, backup |
| 200 | + if _is_endpoints_submission(name): |
| 201 | + log.info( |
| 202 | + "%s is an endpoints submission; nothing to truncate", |
| 203 | + name, |
275 | 204 | ) |
276 | 205 | else: |
277 | 206 | log.error("%s missing", acc_log) |
|
0 commit comments