Skip to content

Commit b3d6e20

Browse files
author
Abraham Sewill
committed
cli: xchplot2 parity-check subcommand
Globs every *_parity binary in ./build/tools/parity (overridable via --dir), execs each in turn, and summarizes PASS/FAIL with per-test wall time. Captures stdout/stderr to /tmp/xchplot2-parity-<name>.log for failed tests so the user can grep the log after. Verified on main: 10/10 PASS (aes, aes_bs, xs, sycl_sort, sycl_g_x, sycl_bucket_offsets, t1, t2, t3, plot_file). Branch-agnostic by design — glob picks up whatever *_parity was built, so cuda-only will see its subset automatically.
1 parent c5ea80d commit b3d6e20

2 files changed

Lines changed: 88 additions & 4 deletions

File tree

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -431,10 +431,11 @@ runs a live k=22 plot across `--devices 0,1`.
431431
### Lower-level subcommands
432432

433433
```bash
434-
xchplot2 test <k> <plot-id-hex> [strength] ... # single plot, raw inputs
435-
xchplot2 batch <manifest.tsv> [-v] [--skip-existing] [--continue-on-error]
436-
[--devices <SPEC>]
437-
xchplot2 verify <file.plot2> [--trials N] # run N random challenges
434+
xchplot2 test <k> <plot-id-hex> [strength] ... # single plot, raw inputs
435+
xchplot2 batch <manifest.tsv> [-v] [--skip-existing] [--continue-on-error]
436+
[--devices <SPEC>]
437+
xchplot2 verify <file.plot2> [--trials N] # run N random challenges
438+
xchplot2 parity-check [--dir PATH] # CPU↔GPU regression screen
438439
```
439440

440441
`verify` opens a `.plot2` through pos2-chip's CPU prover and runs N
@@ -456,6 +457,8 @@ batch — not a replacement for `chia plots check`.
456457
| `ACPP_GFX=gfxXXXX` | AMD only — required at **build** time; sets AOT target for amdgcn ISA. |
457458
| `ACPP_TARGETS=...` | Override AdaptiveCpp target selection (defaults: NVIDIA `generic`, AMD `hip:$ACPP_GFX`). |
458459
| `CUDA_ARCHITECTURES=sm_XX` | Override the CUDA arch autodetected from `nvidia-smi`. |
460+
| `CUDA_PATH=/path/to/cuda` | Override the CUDA Toolkit root for linking (default: `/opt/cuda`, `/usr/local/cuda`). Useful on JetPack / non-standard installs. |
461+
| `CUDA_HOME=/path/to/cuda` | Fallback for `CUDA_PATH` — same effect. |
459462
| `POS2_CHIP_DIR=/path` | Build-time: point at a local pos2-chip checkout instead of FetchContent.|
460463
| `XCHPLOT2_TEST_GPU_COUNT=N` | Override `scripts/test-multi-gpu.sh`'s auto-detected GPU count (forces run / skip without consulting `nvidia-smi`). |
461464

tools/xchplot2/cli.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
#include <algorithm>
1616
#include <cerrno>
17+
#include <chrono>
1718
#include <cstdint>
1819
#include <cstdio>
1920
#include <cstdlib>
2021
#include <cstring>
22+
#include <filesystem>
2123
#include <fstream>
2224
#include <iostream>
2325
#include <stdexcept>
@@ -76,6 +78,11 @@ void print_usage(char const* prog)
7678
<< " Open <plotfile> and run N random challenges through the CPU prover.\n"
7779
<< " Zero proofs across a sensible sample (>=100) strongly indicates a\n"
7880
<< " corrupt plot. Default N=100.\n"
81+
<< " " << prog << " parity-check [--dir PATH]\n"
82+
<< " Run every *_parity binary in PATH and summarize PASS/FAIL.\n"
83+
<< " Default PATH is ./build/tools/parity. Build the tests with\n"
84+
<< " `cmake --build <build-dir>` first. Useful for post-refactor\n"
85+
<< " regression screening.\n"
7986
<< "\n"
8087
<< " test-mode positional args:\n"
8188
<< " <k> : even integer in [18, 32]\n"
@@ -305,6 +312,80 @@ extern "C" int xchplot2_main(int argc, char* argv[])
305312
}
306313
}
307314

315+
if (mode == "parity-check") {
316+
std::string dir = "./build/tools/parity";
317+
for (int i = 2; i < argc; ++i) {
318+
std::string a = argv[i];
319+
if ((a == "--dir" || a == "-d") && i + 1 < argc) {
320+
dir = argv[++i];
321+
} else {
322+
std::cerr << "Error: unknown argument: " << a << "\n";
323+
print_usage(argv[0]);
324+
return 1;
325+
}
326+
}
327+
328+
// Glob every *_parity binary in `dir`. Same code path works for
329+
// both branches — main ships sycl_*_parity extras that cuda-only
330+
// doesn't, and the wildcard picks up whichever actually exists.
331+
std::vector<std::filesystem::path> tests;
332+
std::error_code ec;
333+
if (std::filesystem::is_directory(dir, ec)) {
334+
for (auto const& entry :
335+
std::filesystem::directory_iterator(dir, ec))
336+
{
337+
auto const name = entry.path().filename().string();
338+
constexpr char const kSuffix[] = "_parity";
339+
constexpr size_t kLen = sizeof(kSuffix) - 1;
340+
bool const ends =
341+
name.size() >= kLen &&
342+
name.compare(name.size() - kLen, kLen, kSuffix) == 0;
343+
if (ends && entry.is_regular_file(ec)) {
344+
tests.push_back(entry.path());
345+
}
346+
}
347+
}
348+
if (tests.empty()) {
349+
std::cerr << "No `*_parity` binaries found under " << dir << ".\n"
350+
"Build them first:\n"
351+
" cmake -B build -S . -DCMAKE_BUILD_TYPE=Release\n"
352+
" cmake --build build --parallel\n"
353+
"Then re-run from the repo root, or pass --dir <path>.\n";
354+
return 2;
355+
}
356+
std::sort(tests.begin(), tests.end());
357+
358+
int pass = 0, fail = 0;
359+
std::cerr << "==> parity tests (" << tests.size() << " found in "
360+
<< dir << ")\n";
361+
for (auto const& test : tests) {
362+
auto const name = test.filename().string();
363+
std::string const log_path =
364+
"/tmp/xchplot2-parity-" + name + ".log";
365+
// Redirecting through the shell: `test` is a path we
366+
// generated ourselves from a directory listing — no user-
367+
// controlled shell metachars reach this string.
368+
std::string const cmd =
369+
test.string() + " >" + log_path + " 2>&1";
370+
auto const t0 = std::chrono::steady_clock::now();
371+
int const rc = std::system(cmd.c_str());
372+
auto const ms = std::chrono::duration<double, std::milli>(
373+
std::chrono::steady_clock::now() - t0).count();
374+
if (rc == 0) {
375+
std::fprintf(stderr, " PASS %-32s (%.1f ms)\n",
376+
name.c_str(), ms);
377+
++pass;
378+
} else {
379+
std::fprintf(stderr,
380+
" FAIL %-32s (exit %d; log: %s)\n",
381+
name.c_str(), rc, log_path.c_str());
382+
++fail;
383+
}
384+
}
385+
std::fprintf(stderr, "\n==> %d passed, %d failed\n", pass, fail);
386+
return fail > 0 ? 1 : 0;
387+
}
388+
308389
if (mode == "plot") {
309390
// Standalone farmable-plot path: derive plot_id + memo internally.
310391
int k = 28;

0 commit comments

Comments
 (0)