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
10 changes: 5 additions & 5 deletions docs/contextual-learning.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ This is an implementation contract, not a speedup or platform-validation claim.
每个内容工作线程独占在线模型(online model),分别预测 CPU、CUDA dGPU 和 OpenCL iGPU 的成功哈希服务时间。预测目标是任务服务耗时,不是单独的内核时间、物理磁盘带宽或整个扫描的完成时间。读取、哈希和设备争用相互影响;本模型不宣称因果识别。
Each worker owns independent backend models for successful hash service time, not kernel time or whole-scan makespan. Storage caching and shared-resource pressure remain potential confounders.

输入 payload 字节数为 B,有效更新批量为 L,提交时观测的竞争任务数为 C。四维特征(feature vector)是:
输入 payload 字节数为 B,有效更新批量为 L,竞争任务数代理为 C。决策预测使用选择时在途数;完成后的拟合另外记录真实开始时在途数及任务期间是否有后续重叠,至少不会把两条同时开始的大任务都错标为零争用。它仍不测量重叠持续比例或物理内存带宽。四维特征(feature vector)是:

```text
x = [1, B / 2^20, ceil(B/L) / 1024, (B / 2^20) * C / 1024]
predicted_ms = xᵀ β_backend
```

四项分别表示固定成本、字节成本、批量提交成本和与 payload 交互的竞争成本。CPU/iGPU 的 C 包括共享主机资源的在途任务;CUDA 使用同后端任务数。C 是轻量代理而非带宽测量。设备的名称、厂商、驱动、实现版本、架构、计算单元、硬件线程、内存约束、统一内存属性和实际批量参与设备身份键;它们**不是全部作为回归变量输入**。因此这是本机按设备拟合,不是跨任意 GPU 的零样本性能预测。
The four terms represent fixed, byte, batch and payload–contention costs. Device characteristics namespace learned state; the implementation does not regress every hardware field or promise zero-shot transfer across devices.
四项分别表示固定成本、字节成本、批量提交成本和与 payload 交互的竞争成本。CPU/iGPU 的 C 包括共享主机资源的在途任务;CUDA 使用同后端任务数。C 是轻量代理而非带宽测量。误差诊断始终比较**选择时冻结的预测**与结果,拟合则使用实际观测到的重叠上下文,避免把事后信息误称为决策时已知。设备的名称、厂商、驱动、实现版本、架构、计算单元、硬件线程、内存约束、统一内存属性和实际批量参与设备身份键;它们**不是全部作为回归变量输入**。因此这是本机按设备拟合,不是跨任意 GPU 的零样本性能预测。
The four terms represent fixed, byte, batch and payload–contention costs. Decision prediction uses the selection-time context; fitting uses observed overlap, while the error diagnostic stays tied to the actual decision-time prediction. Contention is still a proxy, not a bandwidth meter or a causal estimate. Device characteristics namespace learned state; this does not promise zero-shot transfer.

## 数学模型 / Mathematical model

Expand All @@ -40,8 +40,8 @@ Fit RMS is distinct from pre-update prediction errors. Neither supplies a calibr
自动模式先检查大小资格、预算和设备可用性,再比较三个候选的预测;CPU 偏好和残差余量是工程启发式。未知或训练域外输入触发有限初始探索,并有周期性确定性探索。该策略不是 LinUCB 或 Thompson sampling,没有遗憾界(regret bound)、无偏反事实估计或全局最优保证。被选择后端才产生标签,存在选择偏差;周期探索不能自动消除缓存、顺序与设备负载混杂。
Routing uses bounded initial and periodic deterministic exploration, not a statistically calibrated bandit algorithm. Only selected devices generate outcomes, so selection bias remains.

核显只有一个池内计算实例:占用时不等待,当前任务可回退 CPU;CUDA 使用工作线程自己的流。`--cpu`、`--cuda`、`--igpu` 覆盖配置,但加速器仍受大小门槛、预算和可用性约束。可恢复计算错误重试 CPU,内容正确性检查不一致仍失败。精确重复判断始终包含逐字节比较。
The iGPU is admitted without waiting; forced accelerator modes remain subject to eligibility and safe fallback. Correctness failures are not hidden as performance fallback.
每个内容工作线程独占 CPU、CUDA 流和核显 OpenCL 队列/内核/设备缓冲,并在自己的模型里比较三个候选。核显复用该线程已有的 CPU 文件读取缓冲;编译程序共享,完整文件任务不再持有池级核显互斥。所有核显实例共同受一个池预算约束,分配额按工作线程数预留;资源不足时不能假装设备可用。初次发现/冷启动仍可使自动模式的其他任务暂走 CPU,但不是稳态单任务限流。`--cpu`、`--cuda`、`--igpu` 覆盖配置,但加速器仍受大小门槛、预算和可用性约束。可恢复计算错误只退休所属线程的设备并完整重试 CPU;内容正确性检查不一致仍失败。精确重复判断始终包含逐字节比较。
Every content worker owns CPU, a CUDA stream, and a private iGPU OpenCL queue/kernel/device buffers. iGPU reuses owner CPU file-I/O buffers while sharing only the compiled program; there is no pool-wide iGPU task lock. Aggregate host/device budgets reserve capacity across all owners. Cold discovery can still make automatic tasks temporarily use CPU, but does not serialize steady-state iGPU file work. Recoverable compute errors retire only the failing owner's backend and retry the complete file on CPU; correctness mismatches still fail.

## 跨运行状态 / Cross-run state

Expand Down
127 changes: 127 additions & 0 deletions docs/igpu-worker-concurrency.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Per-worker iGPU concurrency design (2026-09-27)

## Problem and evidence

The v0.6.0 scheduler has N fixed content workers, each with private CPU and CUDA
execution state, but only one pool-wide `igpu_compute_`, one pair of host buffers,
and an `igpu_busy_` admission flag. The flag remains held for an entire iGPU file
task, so no second worker can dispatch iGPU work even when its own CPU/CUDA state
is idle. This is a software ownership restriction, not an OpenCL requirement.
The OpenCL backend already shares a compiled program/context while allocating
private queues, kernel objects and buffers for each `Device` instance.

The [Khronos OpenCL specification](https://registry.khronos.org/OpenCL/specs/unified/html/OpenCL_API.html)
permits multiple queues in one context and says their commands are independent,
but does not promise physically parallel work-group execution. In particular,
the implementation may serialize work-groups. Concurrent CPU/GPU work can also
contend for a shared memory interface; the [SC '25 shared-memory platform study](https://doi.org/10.1145/3731599.3767497)
is a warning about mechanisms, not a performance estimate for the user's iGPU.

## Required invariants

1. Every eligible content worker owns a private iGPU compute instance and model
state. It reuses its own CPU file-I/O buffers; no second host input pair is
needed because the OpenCL backend copies from them synchronously. Discovery/program
compilation may remain one-time/shared, but full file tasks must not hold a
pool-wide iGPU lock. The first driver startup remains controlled by the cold
admission policy; later per-worker activation is independent.
2. Aggregate host and device allocation budgets must account for **all** worker
iGPU instances, not multiply a one-instance reservation by N. Host budgeting
adds leaf-CV scratch, not duplicate CPU input buffers. Actual batch
capacity remains in the device identity used for persistent model loading.
3. A recoverable compute failure retires only its owning worker's iGPU instance;
a global discovery failure can make the backend unavailable everywhere.
4. Runtime context includes actual in-flight CPU/iGPU contention at selection.
Fitting also incorporates a later-overlap epoch and exact peer count at task
start; prediction-error diagnostics retain the original decision-time estimate.
Existing CUDA peak/contention keys retain their meaning; new iGPU peak and
contended-sample keys are separate. Neither proves simultaneous hardware
kernel work.
5. Forced `--igpu`, explicit training, telemetry, exact digest verification,
fallback correctness, and legacy output/CLI contracts remain intact.

## Verification plan

- Hardware-free two-worker gate test: hold one iGPU task and prove another
worker can independently select iGPU and complete before the first releases.
- Inject per-worker failures and verify no peer retirement or mislabeled model
sample. Verify fixed-budget allocations and startup/probe behavior.
- Full CPU-only Windows Debug suite; Linux/macOS CI and PoCL kernel tests after
push; physical iGPU/CUDA test with full-file digest equivalence.
- Compare 1/2/4 concurrent iGPU instances on matched large-file corpora,
reporting setup-inclusive wall time, total read bytes, physical device overlap
if measurable, CPU throughput, error/fallback counts and peak admitted work.
More queues are not assumed to improve whole-scan throughput.

## Implementation state

The pool-wide iGPU file-task gate was removed. Each worker now lazily owns a
private OpenCL compute instance and model contribution, with aggregate memory
budget divided across all configured workers. CPU/iGPU share owner input buffers
instead of allocating another pair. Initial automatic discovery and cold setup
remain nonblocking for unrelated work; explicit training waits for shared probe
completion and never downgrades a requested backend merely because a peer is
initializing. Setup history is aggregated from owner-local measurements. The
reported iGPU peak counts admitted file tasks, **not** simultaneous hardware
kernel execution. Hardware-free two-worker overlap, per-owner failure isolation,
all-three-backend learning, bounded 12-worker quotas, and 100 repeated iGPU
routing tests pass locally.

The model now uses an exact atomic CPU+iGPU active count for selection features
instead of summing two separately loaded counters. On task completion, a separate
training context takes the maximum of selected context, exact start peers, and a
binary indicator that another task overlapped later. The online error diagnostic
uses the decision-time prediction, so it does not benefit from information that
became available only after dispatch. This remains a coarse contention proxy;
overlap duration and DRAM traffic are not observed.

## Local validation evidence

Windows x64 MSVC 19.51 CPU-only Debug CTest passed 27/27 after the
metric-compatibility and actual-contention edits. The routing test repeated 100
times without a failure after its synchronization assertions were stabilized.
An additional model test verifies that error uses the decision-time prediction
while fitting uses the observed contention feature.

Physical smoke uses Windows 11, MSVC 19.44, CUDA 12.8, the production OpenCL
backend, three 32 MiB distinct files and an isolated `.temp` workspace. With
three workers, 1 MiB file-I/O blocks, 128 MiB host budget and 64 MiB device
budget, `scan --igpu --rehash --summary --format=tsv --no-telemetry` exited 0:
all three file hashes ran on iGPU, none on CPU/CUDA, zero fallback, and
`igpu_peak_concurrency=3`. The executable SHA-256 for that differential run
was `152821C58D6BB15061D801260C140B8F4B9AA9EDB182305124CD04AECA8E80F3`.
Rerunning the same three inputs with `--cpu --rehash` yielded identical three
stored BLAKE3 digests (queried from `state.db`). This demonstrates concurrent
file-task admission and digest correctness, **not physical kernel overlap**.

That forced-iGPU run took 498.139 ms including 110.660 ms discovery and
991.839 ms **summed-worker** setup; the paired CPU run took 33.528 ms. This is
not a claim of GPU acceleration: CPU is clearly preferable for this small
three-file, cold-start workload. A separate `train` over those files completed
with three samples per backend, three saved model keys, and six prior hits;
the next automatic scan selected CPU for all three, with two cold accelerator
starts deferred. This is a desirable decision under the observed setup costs,
not evidence that the devices cannot run concurrently once admitted.

An exploratory local CPU-only rehash of 5,000 distinct 4 KiB files used the
v0.6.0 release archive as baseline and an in-progress version of this branch
as candidate, with order old/new/new/old/old/new/new/old on the same warm
workspace. Median elapsed times were 576.162 ms and 588.274 ms respectively
(+2.1% candidate). The sample is too small and uncontrolled to establish a
regression. After the contention-epoch and compatibility edits, a second
eight-run interleaving on the same workload (new/old/old/new/new/old/old/new)
yielded medians of 578.231 ms candidate and 590.032 ms baseline. The sign
reversed between the two exploratory batches; this is evidence of noise, not
a speedup claim. Preserve both observations and repeat representative
benchmarks before making any broad performance claim.

The final local production-backend rebuild again produced matching digests for
all three 32 MiB files with iGPU and `igpu_peak_concurrency=3`; SHA-256 of the
executable was `26297DDAAEB6A366BB0E370D192155A02E12CEE0A84E414634F2509F9F325E2F`.
After this, a three-backend `train` completed with three samples per backend,
eight prior hits, and three saved keys. A forced CUDA scan hashed all three files
on three CUDA workers, with `gpu_peak_concurrency=3` and digests identical to
the iGPU/CPU results. This confirms both accelerator backends remain usable
and isolated on the same corpus. The current most-recent build may have a
different SHA-256 because metric and model diagnostics changed after this
smoke; the final validation report must name its own binary identity.
2 changes: 1 addition & 1 deletion docs/research/online-model-parameter-audit-2026-09-27.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ CPU observations never directly update CUDA/iGPU coefficients. The risk is oppor

Reproducible diagnostic: use one controlled eligible size band and `--rehash`, record per-run CPU/CUDA/iGPU accepted samples, exploration selections, deferred CUDA/iGPU counts, cold credit/spend and device setup, and compare default auto with a separate forced-device control on the same bytes and randomized execution order. Verify complete outputs and include startup in wall time. A nonzero number of exploration *decisions* without completed device samples is not evidence that the model has learned the device. Do not add unconditional GPU probing solely to make data symmetric: it may regress short scans. If the controlled long-lived workload shows missed benefit, consider a budgeted, shared, size-stratified completed-probe guarantee rather than merely increasing provisional exploration frequency.

An explicit `same train` command now offers an opt-in way to pay for all three backend labels outside ordinary scans; implementation and bounded physical-device smoke are recorded in [train-mode-validation.md](../train-mode-validation.md). Its existence does not imply that an auto scan should proactively start accelerators, nor that its selected corpus represents a production workload.
An explicit `same train` command now offers an opt-in way to pay for all three backend labels outside ordinary scans; implementation and bounded physical-device smoke are recorded in [train-mode-validation.md](../train-mode-validation.md). Its existence does not imply that an auto scan should proactively start accelerators, nor that its selected corpus represents a production workload. The single pool-wide iGPU backend described in the following historical audit was later removed; see [per-worker iGPU concurrency](../igpu-worker-concurrency.md) for the new ownership and validation evidence.

## Lazy versus asynchronous activation (follow-up)

Expand Down
2 changes: 1 addition & 1 deletion docs/telemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ Each worker exports 64 CPU/GPU bands, including unknown cells. Categories use wo

Worker parameters retain actual buffers/budget. Error EWMAs are worker-local, not global. Aggregate known-band counters count worker-band cells, up to workers × 32 per backend.

原始直方图(histogram)保留汇总 `pgo.latency_bucket_us.0`…`.31` / `pgo.residual_bucket_us.0`…`.31` 和逐线程 `worker.<id>.pgo.*`;桶索引为 `floor(log2(us))`、两端饱和,数值是次数而非微秒。每线程另存 CPU/GPU 次数和逻辑字节、初始化与回退、探索和各决策原因(包括 `worker.<id>.cold_start_cpu`:自动模式一次性首设备初始化期间暂走 CPU,不等于永久停用 GPU)、选择时 GPU 在途数、峰值并发与竞争样本数。GPU 在途与峰值统计覆盖选中 GPU 的任务生命周期(含 I/O),不是实际内核忙碌数;`contended_samples` 仅在选择时观察 active>1,不能完整捕捉随后出现的区间重叠。它们用于分析样本碎片化与可能竞争,不构成全局调度模型。
原始直方图(histogram)保留汇总 `pgo.latency_bucket_us.0`…`.31` / `pgo.residual_bucket_us.0`…`.31` 和逐线程 `worker.<id>.pgo.*`;桶索引为 `floor(log2(us))`、两端饱和,数值是次数而非微秒。每线程另存 CPU/CUDA/iGPU 次数和逻辑字节、初始化与回退、探索和各决策原因(包括 `worker.<id>.cold_start_cpu`:自动模式一次性首设备初始化期间暂走 CPU,不等于永久停用 GPU)、选择时 GPU 在途数、峰值并发与竞争样本数。兼容字段 `gpu_peak_concurrency` 与 `worker.<id>.contended_samples` 仍只统计 CUDA;新增 `igpu_peak_concurrency` 与 `worker.<id>.igpu_contended_samples` 单列核显,避免改变现有指标含义。峰值统计覆盖已准入文件任务的生命周期(含 I/O),**不是同时执行内核的硬件证明**。竞争样本结合任务开始时在途数与任务期间新增的重叠事件,仍不测量重叠时长或共享内存带宽。兼容字段 `worker.<id>.igpu_busy` 现在只代表一次性设备探测忙,不再代表稳态核显被池级独占;新增的逐线程核显批容量、预算、初始化耗时及可用状态可用于检查所有权。它们用于分析样本碎片化与可能竞争,不构成全局调度模型。

Histograms retain aggregate and worker-prefixed raw buckets. Bucket indices are saturated floor(log2(us)); values are counts. Per-worker work, initialization/fallback, exploration/decision reasons and concurrency metrics expose fragmentation/contention without creating a global model.

Expand Down
4 changes: 4 additions & 0 deletions include/same/detail/online_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ class OnlineModel {
/// 在更新前记录预测残差,然后累加充分统计量。 / Record pre-update residual then sufficient
/// statistics.
bool observe(BackendKind backend, const Context& context, double service_ms) noexcept;
/// 决策时冻结的预测只用于误差;实际重叠上下文用于拟合。
/// Use the decision-time prediction for error and the observed-overlap context for fitting.
bool observe(BackendKind backend, const Context& context, double service_ms,
Prediction decision_prediction) noexcept;

/// 兼容 CUDA 布尔调用。 / Compatibility for CUDA boolean callers.
Prediction predict(bool gpu, std::uint64_t bytes) const noexcept {
Expand Down
Loading
Loading