Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions npu/forward/include/q4nx_forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ class Q4nxNpuForward {
// Public: a speculative driver outside this class begins a verify batch, then commits a prefix of it.
void begin_verify(int rows, int start_pos);
bool commit_verify_rows(int accepted);
// How many commits took the full-accept path (kept the batch's own state instead of restoring and replaying it).
// A test that compares the two paths reads it to know the path it meant to test is the one that ran.
long full_accepts_kept() const { return full_accepts_kept_; }
bool gdn_apply_rows(int from, int to); // recurrence-only replay of stored rows [from, to)


Expand Down Expand Up @@ -252,6 +255,7 @@ class Q4nxNpuForward {
bool load_norms();
std::vector<float> last_hidden_; // last_hidden(): the post-final-norm state of the last position
std::vector<float> last_residual_; // and one norm earlier: the raw residual of the last position
long full_accepts_kept_ = 0; // commit_verify_rows(): see full_accepts_kept()
std::vector<int> tap_layers_; // engine#1780: set_layer_taps()
std::vector<float>* tap_sink_ = nullptr;
size_t tap_base_ = 0; // where the current pass's rows start in *tap_sink_
Expand Down
1 change: 1 addition & 0 deletions npu/forward/src/q4nx_forward.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2551,6 +2551,7 @@ bool Q4nxNpuForward::commit_verify_rows(int accepted) {
// they are 11 ms + 7 ms per row, 67 ms of an 8-row round. NPU_COMMIT_FULL_REPLAY=1 keeps them, for an A/B.
static const bool always_replay = std::getenv("NPU_COMMIT_FULL_REPLAY") != nullptr;
const bool keep_batch_state = accepted == verify_rows_ && accepted > 0 && !always_replay && !replay_check;
if (keep_batch_state) full_accepts_kept_++;
if (!keep_batch_state) {
for (size_t l = 0; l < conv_state_.size(); l++) conv_state_[l] = snap_conv_[l];
for (size_t l = 0; l < rec_state_.size(); l++) rec_state_[l] = snap_rec_[l];
Expand Down
8 changes: 8 additions & 0 deletions tests/commit_full_accept_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ int run_once(const char* dir, const char* out) {
if (!any) { std::printf("SKIP: the model has no recurrent (GDN) state\n"); return 77; }
}
if (!fwd.step(10, pos, logits)) { std::printf("FAIL step after the commit: %s\n", fwd.last_error()); return 1; }
// The negative control: each run must have taken the path it was started for, or the comparison below would
// compare a path with itself and pass while testing nothing.
const bool replay = std::getenv("NPU_COMMIT_FULL_REPLAY") != nullptr;
if (fwd.full_accepts_kept() != (replay ? 0 : 1)) {
std::printf("FAIL the %s run took the other commit path (%ld full accept(s) kept)\n", replay ? "replay" : "kept",
fwd.full_accepts_kept());
return 1;
}
FILE* f = std::fopen(out, "wb"); // file-create-ok: the test's own scratch file beside its build, removed below
if (!f) return 1;
auto put = [&](const std::vector<std::vector<float>>& vv) {
Expand Down
Loading