tensorfs 0.3.90__tar.gz → 0.3.91__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tensorfs-0.3.90 → tensorfs-0.3.91}/Cargo.lock +3 -3
- {tensorfs-0.3.90 → tensorfs-0.3.91}/Cargo.toml +1 -1
- {tensorfs-0.3.90 → tensorfs-0.3.91}/PKG-INFO +1 -1
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/API.md +16 -5
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/cuda.rs +2 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/cursor.rs +4 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/device.rs +6 -1
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/io.rs +8 -2
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/plane.rs +57 -18
- tensorfs-0.3.91/crates/tensorfs-plane/tests/census.rs +189 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/tests/gpu.rs +6 -3
- {tensorfs-0.3.90 → tensorfs-0.3.91}/pyproject.toml +1 -1
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/_ext.pyi +1 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/errors.py +2 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/Cargo.toml +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/build.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/examples/h3-swiglu-layout.md +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/examples/optional-cache-backfill.md +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/examples/resident-conversion.md +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/examples/resident_conversion_profile.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/asset_update.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/b64.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/ckpt.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/conform.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/ensure.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/fetch.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/ingest.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/main.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/rd.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/repo.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/snap.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/bin/tfs/watch.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/cache_roots.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/canon.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/capability.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/catalog/lock.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/catalog.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/cbor.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/checkpoint.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/checkpoint_root.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/corpus.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/adoption.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/companion_tests.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/estimate.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/graft_tests.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/group_commit_tests.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/history_cost_tests.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/part_rows_tests.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/progress.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/resume_tests.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/retention.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived/roots.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/derived.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/descriptors.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/disk.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/dtype.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/durability.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ensure/admission.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ensure/flight.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ensure.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/err.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/fetch.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/filesystem_identity.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/fill.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/fit.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/gc.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/header.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/home.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ids.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/carrier.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/convert.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/custody.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/fingerprint.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/gguf.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/h3_lora.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/journal.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/mod.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/narrow.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/preflight.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/routes/anima.routes.json +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/routes/anima.spec.json +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/routes/sdxl.routes.json +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/routes/sdxl.spec.json +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/routes.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/source.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/stamp.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/ingest/transaction.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/jcs.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/keyed_roots.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/lib.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/limits.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/machine.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/manifest.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/meta.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/project.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/providers.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/read.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/receipt.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/reclaim.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/registry.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/relation.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/repo_cache.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/repository.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/sha256.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/source_artifact.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/spec.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/staging.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/stats.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/storage.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/store.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/api.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/decisions.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/download.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/http.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/http_reuse_tests.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/hub.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/ledger.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/memory.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/mod.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/policy.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/pull.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/push.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/sources.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/tests/tail.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/transport/tests.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/unsynced.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/src/vectors.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/additive_fields.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/anima_hf_profile.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/as_is.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/catalog_owner_probe.c +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/checkpoint_roots.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/civitai_anima.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/civitai_sdxl_profile.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/ensure.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fd_budget.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fd_headroom.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fetch_faults.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fetch_url_progress.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fit.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fixtures/repo_apply/blobs.jsonl +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_list.jsonl +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_repository.json +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_rows.jsonl +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fixtures/repo_apply/header.cbor +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fixtures/repo_apply/manifest.json +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/fixtures/repo_apply/mutation.json +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/foreign_json.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/h3_lora.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/h3_swiglu.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/home.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/hub_tls.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/import_tree.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/instrument_profiles.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/keyed_roots.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/liveness.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/qwen_image21_profile.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/read_plan.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/reclaim.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/reclaim_run.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/repo_cache.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/repo_store.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/resident_admission.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/routed_single_file.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/sha256_backends.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/sharded_cas.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/source_artifacts.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/source_download.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/source_plan.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/source_prefixes.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/source_preflight.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/staging.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/store_boundaries.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/tensor_schema.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/transfer_memory.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/trust_index.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/version.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/tests/write_through.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/Cargo.toml +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/bin/g1_vmm.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/bin/g2_overlap.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/bin/gpu_bench/mod.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/faults.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/host.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/layout.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/src/lib.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/tests/common/mod.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-plane/tests/host_tier.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-py/Cargo.toml +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-py/src/docs.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-py/src/ensure.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-py/src/errors.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-py/src/ingest.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-py/src/lib.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-py/src/plane.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-py/src/store.rs +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/__init__.py +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/_derived_channel.py +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/_source_channel.py +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/_tensors.py +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/derived.py +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/plane.py +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/plane.pyi +0 -0
- {tensorfs-0.3.90 → tensorfs-0.3.91}/python/tensorfs/py.typed +0 -0
|
@@ -449,7 +449,7 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
|
449
449
|
|
|
450
450
|
[[package]]
|
|
451
451
|
name = "tensorfs-core"
|
|
452
|
-
version = "0.3.
|
|
452
|
+
version = "0.3.91"
|
|
453
453
|
dependencies = [
|
|
454
454
|
"fs2",
|
|
455
455
|
"libc",
|
|
@@ -464,7 +464,7 @@ dependencies = [
|
|
|
464
464
|
|
|
465
465
|
[[package]]
|
|
466
466
|
name = "tensorfs-plane"
|
|
467
|
-
version = "0.3.
|
|
467
|
+
version = "0.3.91"
|
|
468
468
|
dependencies = [
|
|
469
469
|
"libc",
|
|
470
470
|
"libloading",
|
|
@@ -474,7 +474,7 @@ dependencies = [
|
|
|
474
474
|
|
|
475
475
|
[[package]]
|
|
476
476
|
name = "tensorfs-py"
|
|
477
|
-
version = "0.3.
|
|
477
|
+
version = "0.3.91"
|
|
478
478
|
dependencies = [
|
|
479
479
|
"pyo3",
|
|
480
480
|
"tensorfs-core",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# tensorfs.plane — Python API (v3.
|
|
1
|
+
# tensorfs.plane — Python API (v3.2, 2026-10-02)
|
|
2
2
|
|
|
3
3
|
The weight plane moves bytes; cozy-runtime decides. The plane never measures free memory,
|
|
4
4
|
never picks victims among equals, never reorders a schedule. It ships inside the `tensorfs`
|
|
@@ -240,10 +240,16 @@ stream cannot drain is `Poisoned`.
|
|
|
240
240
|
**Poison is latched plane-wide**: an ambiguous driver outcome (a failed unmap or rollback, an
|
|
241
241
|
undrainable copy failure, a driver mapping that disagrees with the books) or a lease dropped
|
|
242
242
|
unreleased makes every later call raise `Poisoned` with the first cause; the runtime replaces
|
|
243
|
-
the executor. A poisoned plane never unmaps, unregisters or frees a range
|
|
244
|
-
touch it): `ws.close()`, `cur.close()` and `p.close()` raise `Poisoned
|
|
245
|
-
|
|
246
|
-
|
|
243
|
+
the executor. A poisoned plane never unmaps, unregisters or frees a range while it lives
|
|
244
|
+
(copies may still touch it): `ws.close()`, `cur.close()` and `p.close()` raise `Poisoned`.
|
|
245
|
+
Capacity never poisons (`BudgetExceeded`, `Shortfall` leave the plane usable).
|
|
246
|
+
|
|
247
|
+
**A plane collected without `close()`** (its handles dropped in any order, or poisoned) is
|
|
248
|
+
torn down when its last handle goes: its threads stop, and once every device has run all
|
|
249
|
+
queued work, its device ranges are unmapped, its handles released and its pinned RAM let go as
|
|
250
|
+
`close()` would. Only a device that cannot be synchronized keeps its ranges and the pinned
|
|
251
|
+
tier until the process exits. Closing is still the contract: collection order decides when
|
|
252
|
+
an unclosed plane ends.
|
|
247
253
|
|
|
248
254
|
## Host tier across processes
|
|
249
255
|
|
|
@@ -274,6 +280,11 @@ plane usable).
|
|
|
274
280
|
|
|
275
281
|
## Changelog
|
|
276
282
|
|
|
283
|
+
- v3.2 2026-10-02 (W3: fd and thread growth per weight set): a plane collected unclosed or
|
|
284
|
+
poisoned is torn down at its last handle (threads, device memory, pinned memfds) once its
|
|
285
|
+
devices are synchronized; before, its reader threads stayed and a poisoned plane kept its
|
|
286
|
+
memfds for the life of the process.
|
|
287
|
+
|
|
277
288
|
- v3.1 2026-10-02 (Xid 31; W3 run 2675): a failed copy is reported only after its stream drained;
|
|
278
289
|
an undrainable one poisons; a poisoned plane never unmaps (close raises `Poisoned`).
|
|
279
290
|
`verify_bytes()` after release raises `Invalid`. Pinned-tier claims: close and eviction punch
|
|
@@ -106,6 +106,7 @@ pub struct Driver {
|
|
|
106
106
|
pub ctx_get_current: F<*mut CUcontext>,
|
|
107
107
|
pub ctx_set_current: F<CUcontext>,
|
|
108
108
|
pub ctx_synchronize: unsafe extern "C" fn() -> CUresult,
|
|
109
|
+
pub mem_get_info: unsafe extern "C" fn(*mut usize, *mut usize) -> CUresult,
|
|
109
110
|
pub stream_create: unsafe extern "C" fn(*mut CUstream, c_uint) -> CUresult,
|
|
110
111
|
pub stream_destroy: F<CUstream>,
|
|
111
112
|
pub stream_synchronize: F<CUstream>,
|
|
@@ -189,6 +190,7 @@ impl Driver {
|
|
|
189
190
|
ctx_get_current: load!(lib, b"cuCtxGetCurrent"),
|
|
190
191
|
ctx_set_current: load!(lib, b"cuCtxSetCurrent"),
|
|
191
192
|
ctx_synchronize: load!(lib, b"cuCtxSynchronize"),
|
|
193
|
+
mem_get_info: load!(lib, b"cuMemGetInfo_v2"),
|
|
192
194
|
stream_create: load!(lib, b"cuStreamCreate"),
|
|
193
195
|
stream_destroy: load!(lib, b"cuStreamDestroy_v2"),
|
|
194
196
|
stream_synchronize: load!(lib, b"cuStreamSynchronize"),
|
|
@@ -72,6 +72,10 @@ pub(crate) struct Cur {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
impl Cur {
|
|
75
|
+
/// (device slot, ring base, ring length, ring handles), for a plane torn down unclosed.
|
|
76
|
+
pub(crate) fn into_ring(self) -> (usize, u64, u64, Vec<Chunk>) {
|
|
77
|
+
(self.dev, self.ring_base, self.ring_len, self.ring_chunks)
|
|
78
|
+
}
|
|
75
79
|
fn streamed_total(&self) -> u64 {
|
|
76
80
|
if self.total == u64::MAX {
|
|
77
81
|
return u64::MAX;
|
|
@@ -431,8 +431,13 @@ impl Mover {
|
|
|
431
431
|
}
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
-
|
|
434
|
+
/// Close the queue: the thread drains its stream, frees its buffers and exits by itself.
|
|
435
|
+
pub fn detach(&self) {
|
|
435
436
|
self.tx.lock().unwrap().take();
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
pub fn stop(&self) {
|
|
440
|
+
self.detach();
|
|
436
441
|
if let Some(t) = self.thread.lock().unwrap().take() {
|
|
437
442
|
let _ = t.join();
|
|
438
443
|
}
|
|
@@ -278,10 +278,16 @@ impl Readers {
|
|
|
278
278
|
self.q.1.notify_one();
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
-
///
|
|
282
|
-
|
|
281
|
+
/// Let the threads exit once the queue is empty; waits for nothing (the caller may be one
|
|
282
|
+
/// of them).
|
|
283
|
+
pub fn stop(&self) {
|
|
283
284
|
self.q.0.lock().unwrap().stop = true;
|
|
284
285
|
self.q.1.notify_all();
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/// Finish queued jobs, then stop the threads.
|
|
289
|
+
pub fn shutdown(&self) {
|
|
290
|
+
self.stop();
|
|
285
291
|
for t in self.threads.lock().unwrap().drain(..) {
|
|
286
292
|
let _ = t.join();
|
|
287
293
|
}
|
|
@@ -1555,33 +1555,72 @@ impl Drop for Plane {
|
|
|
1555
1555
|
}
|
|
1556
1556
|
|
|
1557
1557
|
impl Drop for Inner {
|
|
1558
|
-
/// The last reference can go
|
|
1559
|
-
/// fill queued ends inside that copy's completion
|
|
1560
|
-
///
|
|
1561
|
-
///
|
|
1562
|
-
///
|
|
1558
|
+
/// The last reference can go without `close()`: handles collected in any order, a plane
|
|
1559
|
+
/// dropped with a fill queued (it ends inside that copy's completion), a poisoned plane.
|
|
1560
|
+
/// Its threads stop, and once every device has run all queued work its ranges are unmapped,
|
|
1561
|
+
/// its handles released and its pinned tier let go, exactly as `close()` would. A device
|
|
1562
|
+
/// that cannot be synchronized keeps its ranges and the pinned tier for the life of the
|
|
1563
|
+
/// process: a copy may still touch them.
|
|
1563
1564
|
fn drop(&mut self) {
|
|
1565
|
+
self.readers.stop();
|
|
1566
|
+
for dev in &self.devices {
|
|
1567
|
+
for m in &dev.movers {
|
|
1568
|
+
m.detach();
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1564
1571
|
let c = self.core.get_mut().unwrap_or_else(|p| p.into_inner());
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
settled &= sync_all(&mut h.pending).is_ok();
|
|
1572
|
+
if teardown(&self.devices, c).is_err() {
|
|
1573
|
+
for w in c.sets.iter().flatten() {
|
|
1574
|
+
std::mem::forget(w.host.clone());
|
|
1569
1575
|
}
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/// Free everything the books still hold, after the devices ran all queued work.
|
|
1581
|
+
fn teardown(devices: &[DeviceRt], c: &mut Core) -> Result<()> {
|
|
1582
|
+
for dev in devices {
|
|
1583
|
+
let _g = dev.bind()?;
|
|
1584
|
+
// SAFETY: the device's context is bound.
|
|
1585
|
+
cuda::check("cuCtxSynchronize", unsafe { (cuda::driver()?.ctx_synchronize)() })?;
|
|
1586
|
+
}
|
|
1587
|
+
let mut rings: Vec<(usize, u64, u64, Vec<Chunk>)> = c.cursors.drain().map(|(_, k)| k.into_ring()).collect();
|
|
1588
|
+
for (d, dev) in devices.iter().enumerate() {
|
|
1589
|
+
let _g = dev.bind()?;
|
|
1590
|
+
let mut chunks = Vec::new();
|
|
1591
|
+
for (_, base, len, held) in rings.iter_mut().filter(|r| r.0 == d && r.2 > 0) {
|
|
1592
|
+
device::unmap_span(*base, *len)?;
|
|
1593
|
+
device::free_va(*base, *len)?;
|
|
1594
|
+
chunks.append(held);
|
|
1595
|
+
}
|
|
1596
|
+
for w in c.sets.iter_mut().flatten() {
|
|
1597
|
+
let Some(dw) = w.devs[d].take() else { continue };
|
|
1598
|
+
for (reg, region) in dw.regs.into_iter().zip(&w.layout.regions) {
|
|
1599
|
+
if !reg.chunks.is_empty() {
|
|
1600
|
+
device::unmap_span(dw.base + region.offset, region.span)?;
|
|
1601
|
+
chunks.extend(reg.chunks);
|
|
1576
1602
|
}
|
|
1577
1603
|
}
|
|
1604
|
+
device::free_va(dw.base, w.layout.nbytes)?;
|
|
1578
1605
|
}
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1606
|
+
c.arenas[d].put_idle(chunks);
|
|
1607
|
+
c.arenas[d].release_idle()?;
|
|
1608
|
+
}
|
|
1609
|
+
let first = devices.first().map(|d| d.ctx);
|
|
1610
|
+
for w in c.sets.iter_mut().flatten() {
|
|
1611
|
+
for (r, (h, region)) in w.hregs.iter_mut().zip(&w.layout.regions).enumerate() {
|
|
1612
|
+
if h.registered {
|
|
1613
|
+
let _g = first.map(CtxGuard::enter).transpose()?;
|
|
1614
|
+
w.host.unregister(region.offset)?;
|
|
1615
|
+
h.registered = false;
|
|
1616
|
+
}
|
|
1617
|
+
if matches!(h.state, HState::Ready) {
|
|
1618
|
+
w.host.release(r as u32, region.offset, region.span)?;
|
|
1619
|
+
h.state = HState::Absent;
|
|
1582
1620
|
}
|
|
1583
1621
|
}
|
|
1584
1622
|
}
|
|
1623
|
+
Ok(())
|
|
1585
1624
|
}
|
|
1586
1625
|
|
|
1587
1626
|
#[derive(Debug, Clone, Default)]
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
//! What a plane leaves behind in its process: descriptors, plane memfds, store files and
|
|
2
|
+
//! threads return to the baseline however a plane ends: closed, or collected unclosed with a
|
|
3
|
+
//! handle outliving it. Alone in its binary: the census is process-wide.
|
|
4
|
+
|
|
5
|
+
mod common;
|
|
6
|
+
|
|
7
|
+
use std::time::Duration;
|
|
8
|
+
|
|
9
|
+
use common::*;
|
|
10
|
+
use tensorfs_plane::cuda::{self, CUstream, CtxGuard};
|
|
11
|
+
use tensorfs_plane::{Error, Plane, PlaneConfig, Tier};
|
|
12
|
+
|
|
13
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
14
|
+
struct Census {
|
|
15
|
+
fds: usize,
|
|
16
|
+
memfds: usize,
|
|
17
|
+
store: usize,
|
|
18
|
+
threads: usize,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
fn census(fx: &Fixture) -> Census {
|
|
22
|
+
let root = fx.root.to_string_lossy().to_string();
|
|
23
|
+
let links: Vec<String> = std::fs::read_dir("/proc/self/fd")
|
|
24
|
+
.unwrap()
|
|
25
|
+
.filter_map(|e| std::fs::read_link(e.ok()?.path()).ok())
|
|
26
|
+
.map(|p| p.to_string_lossy().to_string())
|
|
27
|
+
.collect();
|
|
28
|
+
let threads = std::fs::read_dir("/proc/self/task")
|
|
29
|
+
.unwrap()
|
|
30
|
+
.filter_map(|e| std::fs::read_to_string(e.ok()?.path().join("comm")).ok())
|
|
31
|
+
.filter(|name| name.starts_with("tfs-plane"))
|
|
32
|
+
.count();
|
|
33
|
+
Census {
|
|
34
|
+
// The directory read holds one descriptor of its own.
|
|
35
|
+
fds: links.len() - 1,
|
|
36
|
+
memfds: links.iter().filter(|l| l.contains("memfd:tfs-plane")).count(),
|
|
37
|
+
store: links.iter().filter(|l| l.starts_with(&root)).count(),
|
|
38
|
+
threads,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// The baseline: the census once no plane thread is left (a joined thread's task entry can
|
|
43
|
+
/// outlive the join by a moment).
|
|
44
|
+
fn baseline(fx: &Fixture) -> Census {
|
|
45
|
+
let quiet = Census { threads: 0, ..census(fx) };
|
|
46
|
+
let seen = settled(fx, &quiet);
|
|
47
|
+
assert_eq!(seen.threads, 0, "plane threads outlived every plane");
|
|
48
|
+
seen
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// Threads of an unclosed plane exit on their own: wait for the census to settle.
|
|
52
|
+
fn settled(fx: &Fixture, want: &Census) -> Census {
|
|
53
|
+
let mut seen = census(fx);
|
|
54
|
+
for _ in 0..2000 {
|
|
55
|
+
if &seen == want {
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
std::thread::sleep(Duration::from_millis(1));
|
|
59
|
+
seen = census(fx);
|
|
60
|
+
}
|
|
61
|
+
seen
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#[test]
|
|
65
|
+
fn host_planes_leave_no_descriptors_or_threads() {
|
|
66
|
+
let fx = Fixture::new("census");
|
|
67
|
+
let cycle = |closed: bool| {
|
|
68
|
+
let plane = host_only();
|
|
69
|
+
let a = fx.register(&plane, None);
|
|
70
|
+
let b = fx.register(&plane, Some(plane.host_fd(a).unwrap()));
|
|
71
|
+
plane.set_pinned_budget(1 << 30).unwrap();
|
|
72
|
+
let ticket = plane.want(a, Tier::Pinned, None, 0, false).unwrap();
|
|
73
|
+
ticket.wait().unwrap();
|
|
74
|
+
plane.want(b, Tier::Pinned, Some(&[0]), 0, false).unwrap().wait().unwrap();
|
|
75
|
+
if closed {
|
|
76
|
+
plane.close_ws(a).unwrap();
|
|
77
|
+
plane.close().unwrap();
|
|
78
|
+
}
|
|
79
|
+
// Unclosed: a ticket outlives the handle, so the plane ends when the ticket goes.
|
|
80
|
+
drop(plane);
|
|
81
|
+
drop(ticket);
|
|
82
|
+
};
|
|
83
|
+
cycle(true);
|
|
84
|
+
let base = baseline(&fx);
|
|
85
|
+
for closed in [true, false, false, true, false] {
|
|
86
|
+
cycle(closed);
|
|
87
|
+
assert_eq!(settled(&fx, &base), base, "after a plane {}", if closed { "closed" } else { "dropped unclosed" });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const DEV: i32 = 0;
|
|
92
|
+
|
|
93
|
+
struct Stream(CUstream, #[allow(dead_code)] CtxGuard);
|
|
94
|
+
impl Stream {
|
|
95
|
+
fn new() -> Stream {
|
|
96
|
+
let (_, ctx) = cuda::primary_context(DEV).unwrap();
|
|
97
|
+
let g = CtxGuard::enter(ctx).unwrap();
|
|
98
|
+
let mut s: CUstream = std::ptr::null_mut();
|
|
99
|
+
let d = cuda::driver().unwrap();
|
|
100
|
+
cuda::check("cuStreamCreate", unsafe { (d.stream_create)(&mut s, cuda::STREAM_NON_BLOCKING) }).unwrap();
|
|
101
|
+
Stream(s, g)
|
|
102
|
+
}
|
|
103
|
+
fn raw(&self) -> u64 {
|
|
104
|
+
self.0 as u64
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
impl Drop for Stream {
|
|
108
|
+
fn drop(&mut self) {
|
|
109
|
+
let d = cuda::driver().unwrap();
|
|
110
|
+
unsafe {
|
|
111
|
+
(d.stream_synchronize)(self.0);
|
|
112
|
+
(d.stream_destroy)(self.0);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
118
|
+
enum End {
|
|
119
|
+
Closed,
|
|
120
|
+
/// The plane handle goes first; a view of leased bytes holds the last reference.
|
|
121
|
+
Unclosed,
|
|
122
|
+
/// A lease is dropped unreleased: `close` refuses, the plane is collected poisoned.
|
|
123
|
+
Poisoned,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
fn device_cycle(fx: &Fixture, end: End) {
|
|
127
|
+
let p = Plane::open(PlaneConfig {
|
|
128
|
+
devices: vec![DEV],
|
|
129
|
+
readers: 4,
|
|
130
|
+
staging_buffers: 3,
|
|
131
|
+
staging_bytes: 16 << 20,
|
|
132
|
+
..Default::default()
|
|
133
|
+
})
|
|
134
|
+
.unwrap();
|
|
135
|
+
let ws = fx.register(&p, None);
|
|
136
|
+
let s = Stream::new();
|
|
137
|
+
p.set_pinned_budget(1 << 30).unwrap();
|
|
138
|
+
p.want(ws, Tier::Pinned, Some(&[0, 1]), 0, false).unwrap().wait().unwrap();
|
|
139
|
+
p.set_vram_budget(DEV, 1 << 30).unwrap();
|
|
140
|
+
p.want(ws, Tier::Device(DEV), Some(&[0]), 0, false).unwrap().wait().unwrap();
|
|
141
|
+
let home = p.acquire(ws, DEV, 0, s.raw(), None).unwrap();
|
|
142
|
+
let view = home.view().unwrap();
|
|
143
|
+
// Region 1 streams from the pinned tier, region 2 from disk through staging.
|
|
144
|
+
let cur = p.stream(ws, DEV, &[1, 2], 1, 1, 0, "census", None).unwrap();
|
|
145
|
+
cur.acquire(1, s.raw()).unwrap().release(s.raw()).unwrap();
|
|
146
|
+
let last = cur.acquire(2, s.raw()).unwrap();
|
|
147
|
+
home.release(s.raw()).unwrap();
|
|
148
|
+
match end {
|
|
149
|
+
End::Closed => {
|
|
150
|
+
last.release(s.raw()).unwrap();
|
|
151
|
+
drop(view);
|
|
152
|
+
cur.close().unwrap();
|
|
153
|
+
p.close().unwrap();
|
|
154
|
+
}
|
|
155
|
+
End::Unclosed => {
|
|
156
|
+
last.release(s.raw()).unwrap();
|
|
157
|
+
drop(p);
|
|
158
|
+
drop(cur);
|
|
159
|
+
drop(view);
|
|
160
|
+
}
|
|
161
|
+
End::Poisoned => {
|
|
162
|
+
drop(last);
|
|
163
|
+
drop(view);
|
|
164
|
+
drop(cur);
|
|
165
|
+
assert!(matches!(p.close(), Err(Error::Poisoned(_))));
|
|
166
|
+
drop(p);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
#[test]
|
|
172
|
+
#[ignore = "GPU"]
|
|
173
|
+
fn device_planes_leave_no_descriptors_threads_or_device_memory() {
|
|
174
|
+
let fx = Fixture::new("gpu-census");
|
|
175
|
+
let free = || {
|
|
176
|
+
let (_, ctx) = cuda::primary_context(DEV).unwrap();
|
|
177
|
+
let _g = CtxGuard::enter(ctx).unwrap();
|
|
178
|
+
let (mut free, mut total) = (0usize, 0usize);
|
|
179
|
+
cuda::check("cuMemGetInfo", unsafe { (cuda::driver().unwrap().mem_get_info)(&mut free, &mut total) }).unwrap();
|
|
180
|
+
free
|
|
181
|
+
};
|
|
182
|
+
device_cycle(&fx, End::Closed);
|
|
183
|
+
let (base, vram) = (baseline(&fx), free());
|
|
184
|
+
for end in [End::Closed, End::Unclosed, End::Unclosed, End::Poisoned, End::Closed, End::Poisoned] {
|
|
185
|
+
device_cycle(&fx, end);
|
|
186
|
+
assert_eq!(settled(&fx, &base), base, "after a plane ended {end:?}");
|
|
187
|
+
assert_eq!(free(), vram, "device memory after a plane ended {end:?}");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
@@ -662,7 +662,7 @@ mod copy_faults {
|
|
|
662
662
|
|
|
663
663
|
#[test]
|
|
664
664
|
#[ignore = "GPU"]
|
|
665
|
-
fn
|
|
665
|
+
fn an_undrainable_failure_poisons_and_its_ranges_outlive_the_queued_copies() {
|
|
666
666
|
let fx = Fixture::new("gpu-undrained");
|
|
667
667
|
let p = staging_plane();
|
|
668
668
|
let ws = fx.register(&p, None);
|
|
@@ -675,9 +675,12 @@ mod copy_faults {
|
|
|
675
675
|
assert!(matches!(r, Err(Error::Poisoned(_))), "{r:?}");
|
|
676
676
|
assert!(matches!(p.close_ws(ws), Err(Error::Poisoned(_))), "a poisoned plane must not unmap");
|
|
677
677
|
assert!(matches!(p.drop_regions(ws, Tier::Device(DEV), None), Err(Error::Poisoned(_))));
|
|
678
|
+
// Collecting it waits for the device before anything is unmapped: the copies still
|
|
679
|
+
// queued behind the gate land in mapped memory.
|
|
680
|
+
let opener = open_later(&gate);
|
|
678
681
|
drop(p);
|
|
679
|
-
gate.
|
|
680
|
-
|
|
682
|
+
assert!(gate.is_open(), "the plane was torn down while its copies still waited on the device");
|
|
683
|
+
opener.join().unwrap();
|
|
681
684
|
healthy();
|
|
682
685
|
}
|
|
683
686
|
|
|
@@ -22,6 +22,7 @@ from __future__ import annotations
|
|
|
22
22
|
|
|
23
23
|
from . import _ext
|
|
24
24
|
from ._ext import (
|
|
25
|
+
AdapterTargetUnsupported,
|
|
25
26
|
AmbiguousClassification,
|
|
26
27
|
ArchiveRefused,
|
|
27
28
|
ArithOverflow,
|
|
@@ -181,6 +182,7 @@ CODES: dict[str, type[Refusal]] = _ext.CODES
|
|
|
181
182
|
|
|
182
183
|
__all__ = [
|
|
183
184
|
"CODES",
|
|
185
|
+
"AdapterTargetUnsupported",
|
|
184
186
|
"AmbiguousClassification",
|
|
185
187
|
"ArchiveRefused",
|
|
186
188
|
"ArithOverflow",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/examples/optional-cache-backfill.md
RENAMED
|
File without changes
|
|
File without changes
|
{tensorfs-0.3.90 → tensorfs-0.3.91}/crates/tensorfs-core/examples/resident_conversion_profile.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|