freesolo-flash-dev 0.2.42__tar.gz → 0.2.43__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.
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/Dockerfile.worker +6 -1
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/PKG-INFO +1 -1
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/__init__.py +10 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/kernel_warmup.py +18 -1
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/__init__.py +135 -1
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/sft.py +16 -6
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_worker.py +3 -1
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/pyproject.toml +2 -2
- freesolo_flash_dev-0.2.43/tests/test_sft_example_selection.py +36 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_worker_stack.py +225 -6
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.dockerignore +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.env.example +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.gitignore +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/Dockerfile +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/LICENSE +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/README.md +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/cli-style/README.md +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/cli-style/env-setup-survey-dark.png +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/cli-style/env-setup-survey-light.png +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/cli-style/generate.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/cli-style/index.html +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/cli-style/preview.png +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/cli-style/themed-errors.png +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/cli-style/train-config-error-after.png +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/cli-style/train-config-error-before.png +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/docs/kernel-cache.md +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/_channel.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/_fileio.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/_logging.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/_update_check.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/adapter_artifacts.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/catalog.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cli/_tty.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cli/commands.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cli/envpush.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cli/render.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cli/training_doc.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/client/config.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/client/http.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/accounting.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/multiturn_rollout.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/recipe.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/vram.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/_pkg.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/adapter.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/decoding.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/finalize.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/gpu_setup.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/grpo.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/heartbeat.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/hf.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/lora.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/packing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/attn.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/loraplus.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/rl.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/wandb_log.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/envs/archive_policy.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/envs/registry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/lora_rank.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_auth.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_hf_artifacts.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_hf_retry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_http.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_instance.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_instance_bootstrap.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_instance_poll.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_instance_provider.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/_poll.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/api.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/auth.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/gpus.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/jobs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/jobs/builders.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/preflight.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/lambdalabs/pricing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/keys.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/preload.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/slots.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/train/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/train/deps.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/runpod/train/endpoints.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/py.typed +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/runner/checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/runner/deploy.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/runner/lifecycle.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/serve/pricing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/_deps.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/_internal_client.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/_locks.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/_runtime.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/app.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/auth.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/billing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/billing_retry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/db.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/environment_registry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/envs.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/reconcile.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/server/run_registry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/spec.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/infisical-entrypoint.sh +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/conftest.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_b200_rollout_opt.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_chalk_kernels.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_client.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_cost_rewards.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_export.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_grpo_mask_aware.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_grpo_sleep_gate.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_multiturn_rollout.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_open_model_policy.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_runpod_slots.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_spec_and_validation.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_update_check.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_version.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_vl_warmstart_recombine.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_vl_weight_sync.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/uv.lock +0 -0
|
@@ -69,7 +69,12 @@ RUN pip install --no-cache-dir \
|
|
|
69
69
|
# miscomputed with Triton>=3.4 (fla #640) — the fix is fla's TILELANG backend (correct there), so
|
|
70
70
|
# we bake the pinned tilelang==0.1.11 + apache-tvm-ffi==0.1.11 (0.1.12 double-registers TVM-FFI ->
|
|
71
71
|
# `import tilelang` aborts) and KEEP fla on every arch; flash.engine.worker._ensure_fla_fastpath_on_hopper
|
|
72
|
-
# ensures the tilelang backend is live on sm90 before any model import.
|
|
72
|
+
# ensures the tilelang backend is live on sm90 before any model import. The INVERSE holds on
|
|
73
|
+
# B200/sm100: THERE the tilelang chunk_bwd_dqkwg miscomputes gradients while the Triton path is
|
|
74
|
+
# correct — and the pinned fla default-enables tilelang wherever it imports (i.e. everywhere,
|
|
75
|
+
# since it is baked here for Hopper), so the worker opts sm100 out via FLA_TILELANG=0
|
|
76
|
+
# (engine.worker.perf._force_fla_triton_gdn_on_sm100; upstream default-gates tilelang to
|
|
77
|
+
# Hopper-only since fla #975). Validated win vs the old
|
|
73
78
|
# pure-PyTorch fallback (H100 SXM, Qwen3.5 hidden-2560 LoRA): seq4096 4.2x faster / 1.6x less mem,
|
|
74
79
|
# seq16384 12.6x / 1.9x, loss matches to 1.8e-4. fla is from git: the PyPI wheel is a broken stub
|
|
75
80
|
# (no fla.modules). The git URL is PINNED to a commit (not the moving default branch) for
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: freesolo-flash-dev
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.43
|
|
4
4
|
Summary: Flash — managed LoRA post-training (SFT/GRPO) for Freesolo environments, driven by the `flash` CLI
|
|
5
5
|
Project-URL: Homepage, https://github.com/freesolo-co/flash
|
|
6
6
|
Project-URL: Repository, https://github.com/freesolo-co/flash
|
|
@@ -100,6 +100,7 @@ from flash.engine.worker.perf import (
|
|
|
100
100
|
_estimate_params,
|
|
101
101
|
_flash_attn_3_available,
|
|
102
102
|
_flash_attn_available,
|
|
103
|
+
_force_fla_triton_gdn_on_sm100,
|
|
103
104
|
_GpuPeakSampler,
|
|
104
105
|
_liger_default_for_model,
|
|
105
106
|
_memory_mode,
|
|
@@ -108,6 +109,7 @@ from flash.engine.worker.perf import (
|
|
|
108
109
|
_peak_gpu_gb,
|
|
109
110
|
_remove_fla_from_disk,
|
|
110
111
|
_reset_peak_gpu,
|
|
112
|
+
_restrict_fla_gdn_autotune_on_blackwell,
|
|
111
113
|
_sdpa_cudnn_ctx,
|
|
112
114
|
free_gpu,
|
|
113
115
|
fused_optim_name,
|
|
@@ -265,9 +267,15 @@ def main():
|
|
|
265
267
|
raise RetriableInfraError(
|
|
266
268
|
f"DONE present but metrics.json unreadable after retries (transient HF): {last_err}"
|
|
267
269
|
)
|
|
270
|
+
# BEFORE any model import / fla dispatch: on sm100 the baked tilelang GDN backend
|
|
271
|
+
# computes wrong gradients — opt out so fla uses its (correct-there) Triton path.
|
|
272
|
+
_force_fla_triton_gdn_on_sm100()
|
|
268
273
|
_ensure_fla_fastpath_on_hopper()
|
|
269
274
|
# Must run AFTER fla fast path (may reinstall tilelang) and BEFORE model/vLLM import.
|
|
270
275
|
_neutralize_tilelang_cudart_stub()
|
|
276
|
+
# AFTER the fla fast path (which may (re)install fla), BEFORE any model import / GDN
|
|
277
|
+
# launch: restrict fla's Blackwell GDN bwd autotune to grad-correct configs (fla #913).
|
|
278
|
+
_restrict_fla_gdn_autotune_on_blackwell()
|
|
271
279
|
heartbeat("boot", gpu=gpu_diagnostics(include_torch=False))
|
|
272
280
|
finalize_alloc_conf_for_sleep()
|
|
273
281
|
load_mega_cache()
|
|
@@ -344,6 +352,7 @@ __all__ = [
|
|
|
344
352
|
"_finalize",
|
|
345
353
|
"_flash_attn_3_available",
|
|
346
354
|
"_flash_attn_available",
|
|
355
|
+
"_force_fla_triton_gdn_on_sm100",
|
|
347
356
|
"_grpo_is_no_op_failure",
|
|
348
357
|
"_grpo_resume_already_complete",
|
|
349
358
|
"_hf_upload",
|
|
@@ -359,6 +368,7 @@ __all__ = [
|
|
|
359
368
|
"_remove_fla_from_disk",
|
|
360
369
|
"_reset_peak_gpu",
|
|
361
370
|
"_resolve_adapter_ref",
|
|
371
|
+
"_restrict_fla_gdn_autotune_on_blackwell",
|
|
362
372
|
"_sdpa_cudnn_ctx",
|
|
363
373
|
"assert_adapter_delta_nonzero",
|
|
364
374
|
"assert_adapter_load_clean",
|
{freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/kernel_warmup.py
RENAMED
|
@@ -77,7 +77,9 @@ def _require_gpu():
|
|
|
77
77
|
if not torch.cuda.is_available():
|
|
78
78
|
_log("no CUDA device visible — kernel warmup must run on a GPU builder; nothing baked")
|
|
79
79
|
return None
|
|
80
|
-
_log(
|
|
80
|
+
_log(
|
|
81
|
+
f"GPU: {torch.cuda.get_device_name(0)} ({_torch_sm(torch)}), torch {torch.__version__}"
|
|
82
|
+
)
|
|
81
83
|
return torch
|
|
82
84
|
except Exception as e:
|
|
83
85
|
_log(f"torch unavailable ({e}); cannot warm kernels")
|
|
@@ -128,6 +130,13 @@ def warm_flash_attn(torch) -> bool:
|
|
|
128
130
|
def warm_fla_gdn(torch) -> bool:
|
|
129
131
|
"""Compile flash-linear-attention's Gated-DeltaNet chunk kernels (Qwen3.5/3.6 hybrid path)."""
|
|
130
132
|
try:
|
|
133
|
+
# sm100: tilelang's GDN bwd miscomputes grads — warm the Triton path the worker will run.
|
|
134
|
+
try:
|
|
135
|
+
from flash.engine.worker.perf import _force_fla_triton_gdn_on_sm100
|
|
136
|
+
|
|
137
|
+
_force_fla_triton_gdn_on_sm100()
|
|
138
|
+
except Exception as e:
|
|
139
|
+
_log(f"sm100 fla tilelang opt-out skipped: {e}")
|
|
131
140
|
# fla #640: GDN chunk_bwd needs tilelang on Hopper; Triton path miscomputes/raises there.
|
|
132
141
|
try:
|
|
133
142
|
from flash.engine.worker.perf import _ensure_fla_fastpath_on_hopper
|
|
@@ -135,6 +144,14 @@ def warm_fla_gdn(torch) -> bool:
|
|
|
135
144
|
_ensure_fla_fastpath_on_hopper()
|
|
136
145
|
except Exception as e:
|
|
137
146
|
_log(f"hopper fla fast-path setup skipped: {e}")
|
|
147
|
+
# fla #913: on Blackwell, warm the SAME restricted autotune space the worker boot will
|
|
148
|
+
# run (grad-correct configs only) so the baked cache holds the config that actually runs.
|
|
149
|
+
try:
|
|
150
|
+
from flash.engine.worker.perf import _restrict_fla_gdn_autotune_on_blackwell
|
|
151
|
+
|
|
152
|
+
_restrict_fla_gdn_autotune_on_blackwell()
|
|
153
|
+
except Exception as e:
|
|
154
|
+
_log(f"blackwell fla autotune restriction skipped: {e}")
|
|
138
155
|
from fla.ops.gated_delta_rule import chunk_gated_delta_rule
|
|
139
156
|
|
|
140
157
|
b, h, t, d = 1, 4, 256, 64
|
{freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/flash/engine/worker/perf/__init__.py
RENAMED
|
@@ -131,7 +131,7 @@ def _find_real_libcudart() -> str | None:
|
|
|
131
131
|
with open("/proc/self/maps") as f:
|
|
132
132
|
for line in f:
|
|
133
133
|
if base in line and "/" in line:
|
|
134
|
-
p = line[line.index("/"):].rstrip()
|
|
134
|
+
p = line[line.index("/") :].rstrip()
|
|
135
135
|
if os.path.basename(p).startswith(base) and os.path.exists(p):
|
|
136
136
|
return os.path.realpath(p)
|
|
137
137
|
except OSError:
|
|
@@ -208,6 +208,138 @@ def _neutralize_tilelang_cudart_stub() -> None:
|
|
|
208
208
|
print(f"[worker] libcudart stub neutralize failed: {e}", flush=True)
|
|
209
209
|
|
|
210
210
|
|
|
211
|
+
def _force_fla_triton_gdn_on_sm100() -> None:
|
|
212
|
+
"""Opt fla OUT of its tilelang GDN backend on B200 (sm100) via ``FLA_TILELANG=0``.
|
|
213
|
+
|
|
214
|
+
The worker image bakes tilelang for the HOPPER fast path (fla #640), but the pinned fla
|
|
215
|
+
default-enables its tilelang backend WHEREVER tilelang imports. On sm100, tilelang's
|
|
216
|
+
``chunk_bwd_dqkwg`` computes WRONG GRADIENTS — measured on a real B200 with this exact image
|
|
217
|
+
at the production Qwen3.5/3.6 GDN call shapes (H==HV after transformers' head repeat):
|
|
218
|
+
dq/dk rel-err ~0.72, dg ~1.28 vs the fp32 reference, deterministic, in bf16 AND fp32, while
|
|
219
|
+
the same shapes on H200 are correct to ~4e-3. This is the root cause of the B200 35B-A3B SFT
|
|
220
|
+
incident (grad_norm ~1e8 from the first logged step; loss flat at LR 2e-5/5e-5, collapse at
|
|
221
|
+
1e-4 — garbage gradient DIRECTIONS no LR can fix, while H200 trained healthily at 1e-4).
|
|
222
|
+
|
|
223
|
+
``FLA_TILELANG=0`` flips fla's dispatch to its Triton chunk_bwd_dqkwg — verified correct on
|
|
224
|
+
sm100 at the same shapes (~4e-3). Upstream has since stopped default-enabling tilelang
|
|
225
|
+
off-Hopper (fla #975 gates the default to sm90 + Triton>=3.4) and an explicit env opt-out
|
|
226
|
+
wins on every fla version, so this env set reproduces upstream's current gate on our pin and
|
|
227
|
+
stays a correct no-op across a future pin bump.
|
|
228
|
+
|
|
229
|
+
* ``setdefault``: an explicitly pre-set FLA_TILELANG (e.g. testing a fixed tilelang) wins.
|
|
230
|
+
* sm100 only: sm90 NEEDS tilelang (fla #640, the fast-path installer owns it); sm89/sm120
|
|
231
|
+
train healthily today under the pin's default and upstream's next-pin gate flips them to
|
|
232
|
+
Triton anyway — no evidence to justify changing them from here.
|
|
233
|
+
* Env is read live per-dispatch by fla, but set it at boot BEFORE any model import so no
|
|
234
|
+
kernel ever launches under the old default.
|
|
235
|
+
"""
|
|
236
|
+
try:
|
|
237
|
+
import torch
|
|
238
|
+
|
|
239
|
+
if not (torch.cuda.is_available() and torch.cuda.get_device_capability() == (10, 0)):
|
|
240
|
+
return
|
|
241
|
+
except Exception:
|
|
242
|
+
return
|
|
243
|
+
prior = os.environ.get("FLA_TILELANG")
|
|
244
|
+
if prior is not None:
|
|
245
|
+
print(
|
|
246
|
+
f"[blackwell] FLA_TILELANG={prior!r} pre-set; respecting it "
|
|
247
|
+
"(default here is 0 on sm100: tilelang chunk_bwd_dqkwg miscomputes grads)",
|
|
248
|
+
flush=True,
|
|
249
|
+
)
|
|
250
|
+
return
|
|
251
|
+
os.environ["FLA_TILELANG"] = "0"
|
|
252
|
+
print(
|
|
253
|
+
"[blackwell] sm100 (B200): FLA_TILELANG=0 -> fla GDN uses the Triton chunk_bwd_dqkwg "
|
|
254
|
+
"(tilelang backend computes wrong gradients on sm100; measured dq/dk ~0.72, dg ~1.28 "
|
|
255
|
+
"rel-err; upstream default-gates tilelang to Hopper since fla #975)",
|
|
256
|
+
flush=True,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _restrict_fla_gdn_autotune_on_blackwell() -> None:
|
|
261
|
+
"""Restrict fla's GDN ``prepare_wy_repr_bwd_kernel`` autotune space on Blackwell (sm100/sm120).
|
|
262
|
+
|
|
263
|
+
Defense-in-depth for the Triton GDN backward path — the path sm100 defaults to once
|
|
264
|
+
``_force_fla_triton_gdn_on_sm100`` opts out of tilelang. Upstream reports that Blackwell can
|
|
265
|
+
select unstable Triton configs for this kernel during autotuning (fla #913) and restricted
|
|
266
|
+
the space to the B200-validated config (num_warps=2, num_stages=4) in fla #1000 (ac6c648) —
|
|
267
|
+
NEWER than the worker's pinned fla SHA — so apply the same restriction in-process at boot,
|
|
268
|
+
before any GDN kernel launch. (Not the 35B-A3B incident root cause — that was tilelang, see
|
|
269
|
+
above — but there is no reason to keep autotuning over configs upstream deemed unstable on
|
|
270
|
+
the exact card we train on.)
|
|
271
|
+
|
|
272
|
+
* No-op on non-Blackwell arches, when fla is absent (pure-PyTorch delta path), or when the
|
|
273
|
+
pinned fla already carries the upstream fix (filtering an already-restricted space).
|
|
274
|
+
* Fail-CLOSED like the Hopper fast path: if fla is present on Blackwell but the restriction
|
|
275
|
+
cannot be applied (autotuner layout changed — e.g. an unreviewed pin bump), physically
|
|
276
|
+
remove fla so transformers falls back to the pure-PyTorch delta rule. Slow-but-correct
|
|
277
|
+
beats a run that burns GPU-hours computing garbage gradients.
|
|
278
|
+
* sm120 is included to match upstream's IS_NVIDIA_BLACKWELL gate: 5090 smokes trained fine on
|
|
279
|
+
the unrestricted space, but that is autotune luck (the winning config varies per shape/run),
|
|
280
|
+
not evidence of safety.
|
|
281
|
+
"""
|
|
282
|
+
try:
|
|
283
|
+
import torch
|
|
284
|
+
|
|
285
|
+
if not (torch.cuda.is_available() and torch.cuda.get_device_capability()[0] in (10, 12)):
|
|
286
|
+
return
|
|
287
|
+
except Exception:
|
|
288
|
+
return
|
|
289
|
+
try:
|
|
290
|
+
import importlib.util
|
|
291
|
+
|
|
292
|
+
if importlib.util.find_spec("fla") is None:
|
|
293
|
+
return # no fla -> transformers already uses the pure-PyTorch delta path
|
|
294
|
+
except Exception:
|
|
295
|
+
return
|
|
296
|
+
|
|
297
|
+
def _fail_closed(reason: str) -> None:
|
|
298
|
+
_removed, _still = _remove_fla_from_disk()
|
|
299
|
+
print(
|
|
300
|
+
f"[blackwell] fla GDN autotune restriction FAILED ({reason}) -> DISABLING fla "
|
|
301
|
+
f"(removed {len(_removed)} copy(ies); still_importable={_still}); "
|
|
302
|
+
"pure-PyTorch delta fallback (fla #913: unrestricted autotune miscomputes grads)",
|
|
303
|
+
flush=True,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
try:
|
|
307
|
+
from fla.ops.gated_delta_rule import wy_fast
|
|
308
|
+
|
|
309
|
+
tuner = getattr(wy_fast, "prepare_wy_repr_bwd_kernel", None)
|
|
310
|
+
for _ in range(8): # unwrap decorator layers (heuristics/cache) down to the Autotuner
|
|
311
|
+
if tuner is None or hasattr(tuner, "configs"):
|
|
312
|
+
break
|
|
313
|
+
tuner = getattr(tuner, "fn", None)
|
|
314
|
+
configs = getattr(tuner, "configs", None)
|
|
315
|
+
if not configs:
|
|
316
|
+
_fail_closed("prepare_wy_repr_bwd_kernel autotuner not found")
|
|
317
|
+
return
|
|
318
|
+
keep = [
|
|
319
|
+
c
|
|
320
|
+
for c in configs
|
|
321
|
+
if getattr(c, "num_warps", None) == 2 and getattr(c, "num_stages", None) == 4
|
|
322
|
+
]
|
|
323
|
+
if not keep:
|
|
324
|
+
_fail_closed("no B200-validated config (num_warps=2/num_stages=4) in autotune space")
|
|
325
|
+
return
|
|
326
|
+
if len(keep) == len(configs):
|
|
327
|
+
print(
|
|
328
|
+
"[blackwell] fla GDN autotune already restricted (pinned fla carries fla #1000)",
|
|
329
|
+
flush=True,
|
|
330
|
+
)
|
|
331
|
+
return
|
|
332
|
+
tuner.configs = keep
|
|
333
|
+
print(
|
|
334
|
+
f"[blackwell] fla GDN prepare_wy_repr_bwd autotune restricted {len(configs)} -> "
|
|
335
|
+
f"{len(keep)} config(s) (num_warps=2/num_stages=4; fla #913/#1000 grad miscompute)",
|
|
336
|
+
flush=True,
|
|
337
|
+
)
|
|
338
|
+
except Exception as e:
|
|
339
|
+
with contextlib.suppress(Exception):
|
|
340
|
+
_fail_closed(f"{type(e).__name__}: {e}")
|
|
341
|
+
|
|
342
|
+
|
|
211
343
|
def _ensure_fla_fastpath_on_hopper() -> None:
|
|
212
344
|
"""Enable fla's tilelang GDN backend on Hopper (sm90); no-op elsewhere.
|
|
213
345
|
|
|
@@ -334,6 +466,7 @@ __all__ = [
|
|
|
334
466
|
"_flash_attn_3_available",
|
|
335
467
|
"_flash_attn_available",
|
|
336
468
|
"_float_or_none",
|
|
469
|
+
"_force_fla_triton_gdn_on_sm100",
|
|
337
470
|
"_int_or_none",
|
|
338
471
|
"_liger_default_for_model",
|
|
339
472
|
"_memory_mode",
|
|
@@ -344,6 +477,7 @@ __all__ = [
|
|
|
344
477
|
"_query_nvidia_processes",
|
|
345
478
|
"_remove_fla_from_disk",
|
|
346
479
|
"_reset_peak_gpu",
|
|
480
|
+
"_restrict_fla_gdn_autotune_on_blackwell",
|
|
347
481
|
"_round_gb_from_mib",
|
|
348
482
|
"_sdpa_cudnn_ctx",
|
|
349
483
|
"free_gpu",
|
|
@@ -99,6 +99,21 @@ def _model_arch_dims(model_id: str) -> tuple[int, int]:
|
|
|
99
99
|
return c_hidden, c_layers
|
|
100
100
|
|
|
101
101
|
|
|
102
|
+
def select_sft_examples(train, max_examples, seed):
|
|
103
|
+
"""Pick the SFT sample: the first ``max_examples`` rows of the dataset (file order), shuffled.
|
|
104
|
+
|
|
105
|
+
The slice happens BEFORE the shuffle so ``max_examples`` is a deterministic prefix fence,
|
|
106
|
+
not a random subsample. A train.jsonl that carries fully-labeled SFT rows first and
|
|
107
|
+
prompt-only (empty-output) GRPO rows after can cap SFT to the labeled head — an empty
|
|
108
|
+
completion can never be shuffled into the SFT sample and teach the model to emit nothing.
|
|
109
|
+
"""
|
|
110
|
+
if max_examples > 0:
|
|
111
|
+
train = train[:max_examples]
|
|
112
|
+
rng = random.Random(seed)
|
|
113
|
+
rng.shuffle(train)
|
|
114
|
+
return train
|
|
115
|
+
|
|
116
|
+
|
|
102
117
|
def run_sft():
|
|
103
118
|
from datasets import Dataset
|
|
104
119
|
from transformers import AutoTokenizer
|
|
@@ -122,12 +137,7 @@ def run_sft():
|
|
|
122
137
|
val = getattr(_t, name, None) if _t else None
|
|
123
138
|
return val if val is not None else default
|
|
124
139
|
|
|
125
|
-
train = env.dataset()
|
|
126
|
-
rng = random.Random(_w.SEED)
|
|
127
|
-
rng.shuffle(train)
|
|
128
|
-
max_examples = int(_train_opt("max_examples", 0) or 0)
|
|
129
|
-
if max_examples > 0:
|
|
130
|
-
train = train[:max_examples]
|
|
140
|
+
train = select_sft_examples(env.dataset(), int(_train_opt("max_examples", 0) or 0), _w.SEED)
|
|
131
141
|
texts = []
|
|
132
142
|
multiturn_targets = 0
|
|
133
143
|
for ex in train:
|
|
@@ -41,7 +41,9 @@ WORKER_DEPS = [
|
|
|
41
41
|
"wandb>=0.17",
|
|
42
42
|
# fla from git: PyPI wheel is a broken stub missing fla.modules. SHA-pinned for reproducibility;
|
|
43
43
|
# keep in lockstep with Dockerfile.worker. fla kept on ALL arches — worker ensures tilelang
|
|
44
|
-
# backend on sm90 before model import (fla #640: chunk_bwd miscompute with Triton>=3.4 on Hopper)
|
|
44
|
+
# backend on sm90 before model import (fla #640: chunk_bwd miscompute with Triton>=3.4 on Hopper)
|
|
45
|
+
# and OPTS OUT of tilelang on sm100 (B200) where tilelang's chunk_bwd_dqkwg miscomputes grads
|
|
46
|
+
# (worker _force_fla_triton_gdn_on_sm100; upstream default-gates tilelang to Hopper since fla #975).
|
|
45
47
|
"flash-linear-attention @ git+https://github.com/fla-org/flash-linear-attention.git@f0e213dbd8b5fb90c3c7eca869ac1706d5377139",
|
|
46
48
|
# tilelang version-pinned in lockstep with Dockerfile.worker + perf.py runtime reinstall.
|
|
47
49
|
"tilelang==0.1.11",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "freesolo-flash-dev"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.43"
|
|
4
4
|
description = "Flash — managed LoRA post-training (SFT/GRPO) for Freesolo environments, driven by the `flash` CLI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
# RunPod Flash supports Python 3.11-3.12 (not 3.13 yet).
|
|
@@ -106,7 +106,7 @@ artifacts = ["flash/py.typed"]
|
|
|
106
106
|
# auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
|
|
107
107
|
# PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
|
|
108
108
|
# dev-channel release = bump this (and [project].version) and merge to `dev`.
|
|
109
|
-
version = "0.2.
|
|
109
|
+
version = "0.2.43"
|
|
110
110
|
|
|
111
111
|
[tool.pytest.ini_options]
|
|
112
112
|
pythonpath = ["."]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""``max_examples`` must fence SFT to the HEAD of train.jsonl, slicing BEFORE the shuffle.
|
|
2
|
+
|
|
3
|
+
A dataset may carry fully-labeled SFT rows first and prompt-only (empty-output) GRPO rows
|
|
4
|
+
after; with shuffle-then-slice an empty completion gets sampled into SFT and trains the
|
|
5
|
+
model to emit nothing. Regression for the shuffle-before-slice ordering in run_sft.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from flash.engine.worker.sft import select_sft_examples
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_max_examples_is_a_prefix_fence_not_a_random_subsample():
|
|
14
|
+
# rows 0..9 are labeled SFT rows; rows 10..19 are prompt-only GRPO rows (output="")
|
|
15
|
+
labeled = [{"input": f"q{i}", "output": f"a{i}"} for i in range(10)]
|
|
16
|
+
prompt_only = [{"input": f"p{i}", "output": ""} for i in range(10)]
|
|
17
|
+
picked = select_sft_examples(labeled + prompt_only, 10, seed=0)
|
|
18
|
+
assert len(picked) == 10
|
|
19
|
+
assert sorted(r["input"] for r in picked) == sorted(r["input"] for r in labeled)
|
|
20
|
+
# the property that actually matters: no empty completion leaks into the SFT sample
|
|
21
|
+
assert all(r["output"] for r in picked)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_selection_is_seed_deterministic_but_still_shuffled():
|
|
25
|
+
rows = list(range(100))
|
|
26
|
+
a = select_sft_examples(list(rows), 50, seed=7)
|
|
27
|
+
b = select_sft_examples(list(rows), 50, seed=7)
|
|
28
|
+
assert a == b # same seed -> same training order
|
|
29
|
+
assert sorted(a) == list(range(50)) # exactly the head of the file...
|
|
30
|
+
assert a != list(range(50)) # ...but shuffled for training
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_zero_or_unset_max_examples_keeps_the_full_dataset():
|
|
34
|
+
rows = list(range(20))
|
|
35
|
+
out = select_sft_examples(list(rows), 0, seed=3)
|
|
36
|
+
assert sorted(out) == rows
|
|
@@ -400,7 +400,9 @@ def test_heartbeat_rolls_back_slot_when_upload_reports_failure(monkeypatch):
|
|
|
400
400
|
import flash.engine.worker as w
|
|
401
401
|
|
|
402
402
|
monkeypatch.setattr(w, "_HB_MIN_INTERVAL_S", 0.0)
|
|
403
|
-
sentinel_last_upload =
|
|
403
|
+
sentinel_last_upload = (
|
|
404
|
+
123.0 # a prior successful-commit timestamp the failed retry must restore
|
|
405
|
+
)
|
|
404
406
|
monkeypatch.setattr(w, "_HB_LAST_UPLOAD", sentinel_last_upload)
|
|
405
407
|
|
|
406
408
|
calls = []
|
|
@@ -471,8 +473,12 @@ def test_critical_stages_wait_longer_for_upload_lock(monkeypatch):
|
|
|
471
473
|
finally:
|
|
472
474
|
hbmod._HB_UPLOAD_LOCK.release()
|
|
473
475
|
|
|
474
|
-
assert progress_wait < 0.3,
|
|
475
|
-
|
|
476
|
+
assert progress_wait < 0.3, (
|
|
477
|
+
f"progress stage should skip after the short timeout, waited {progress_wait:.2f}s"
|
|
478
|
+
)
|
|
479
|
+
assert critical_wait >= 0.3, (
|
|
480
|
+
f"critical stage should wait the long timeout, waited {critical_wait:.2f}s"
|
|
481
|
+
)
|
|
476
482
|
assert critical_wait > progress_wait + 0.15
|
|
477
483
|
|
|
478
484
|
|
|
@@ -1019,7 +1025,9 @@ def test_tilelang_pin_is_consistent_and_pinned():
|
|
|
1019
1025
|
perf_src = (root / "flash" / "engine" / "worker" / "perf" / "__init__.py").read_text()
|
|
1020
1026
|
# perf/__init__.py builds the spec via an f-string `f"tilelang=={TILELANG_PIN}"`, so assert the constant.
|
|
1021
1027
|
pm = re.search(r'TILELANG_PIN\s*=\s*"([0-9][0-9A-Za-z.\-]*)"', perf_src)
|
|
1022
|
-
assert pm,
|
|
1028
|
+
assert pm, (
|
|
1029
|
+
"perf/__init__.py must define a pinned TILELANG_PIN constant for the runtime reinstall"
|
|
1030
|
+
)
|
|
1023
1031
|
assert pm.group(1) == pin, (
|
|
1024
1032
|
f"perf/__init__.py TILELANG_PIN must match WORKER_DEPS (deps={pin}, perf={pm.group(1)})"
|
|
1025
1033
|
)
|
|
@@ -1188,7 +1196,9 @@ def test_neutralize_never_loads_the_stub_into_the_process(tmp_path, monkeypatch)
|
|
|
1188
1196
|
if not os.path.exists("/proc/self/maps"):
|
|
1189
1197
|
import pytest
|
|
1190
1198
|
|
|
1191
|
-
pytest.skip(
|
|
1199
|
+
pytest.skip(
|
|
1200
|
+
"/proc/self/maps unavailable (non-Linux); the loaded-mapping assertion needs it"
|
|
1201
|
+
)
|
|
1192
1202
|
|
|
1193
1203
|
pkg = tmp_path / "tilelang"
|
|
1194
1204
|
(pkg / "lib").mkdir(parents=True)
|
|
@@ -1306,7 +1316,216 @@ def test_find_real_libcudart_finds_cu13_wheel_layout(tmp_path, monkeypatch):
|
|
|
1306
1316
|
monkeypatch.setattr(ctypes.util, "find_library", lambda _n: None)
|
|
1307
1317
|
_real_glob = glob.glob
|
|
1308
1318
|
monkeypatch.setattr(
|
|
1309
|
-
glob, "glob", lambda p, *a, **k:
|
|
1319
|
+
glob, "glob", lambda p, *a, **k: [] if p.startswith("/usr") else _real_glob(p, *a, **k)
|
|
1310
1320
|
)
|
|
1311
1321
|
|
|
1312
1322
|
assert perf._find_real_libcudart() == os.path.realpath(real)
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
# ---------------------------------------------------------------------------
|
|
1326
|
+
# Blackwell fla GDN autotune restriction (fla #913 / #1000): on sm100/sm120 the
|
|
1327
|
+
# unrestricted prepare_wy_repr_bwd autotune space can select grad-miscomputing
|
|
1328
|
+
# configs (live B200 Qwen3.6-35B-A3B SFT: grad_norm ~1e8 from the first logged
|
|
1329
|
+
# step, loss flat or collapsing at every LR, while H200 trained healthily). The
|
|
1330
|
+
# worker restricts the space in-process to the B200-validated config, and fails
|
|
1331
|
+
# CLOSED (disables fla -> pure-PyTorch delta) when it cannot.
|
|
1332
|
+
# ---------------------------------------------------------------------------
|
|
1333
|
+
def _blackwell_torch(cc=(10, 0)):
|
|
1334
|
+
"""A stub ``torch`` that looks like a Blackwell card with CUDA available."""
|
|
1335
|
+
t = types.ModuleType("torch")
|
|
1336
|
+
t.cuda = types.SimpleNamespace(
|
|
1337
|
+
is_available=lambda: True,
|
|
1338
|
+
get_device_capability=lambda *a: cc,
|
|
1339
|
+
)
|
|
1340
|
+
return t
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
class _TunerCfg:
|
|
1344
|
+
def __init__(self, num_warps: int, num_stages: int) -> None:
|
|
1345
|
+
self.num_warps = num_warps
|
|
1346
|
+
self.num_stages = num_stages
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
class _FakeTuner:
|
|
1350
|
+
def __init__(self, configs) -> None:
|
|
1351
|
+
self.configs = configs
|
|
1352
|
+
|
|
1353
|
+
|
|
1354
|
+
class _TunerWrapper:
|
|
1355
|
+
"""Decorator layer (heuristics/cache wrapper) the unwrap walk descends through via ``.fn``."""
|
|
1356
|
+
|
|
1357
|
+
def __init__(self, fn) -> None:
|
|
1358
|
+
self.fn = fn
|
|
1359
|
+
|
|
1360
|
+
|
|
1361
|
+
_FULL_SPACE = [(2, 2), (2, 3), (2, 4), (4, 2), (4, 3), (4, 4)]
|
|
1362
|
+
|
|
1363
|
+
|
|
1364
|
+
def _patch_blackwell_stack(monkeypatch, *, cc=(10, 0), fla_present: bool = True, kernel=None):
|
|
1365
|
+
"""Wire the perf helper's touchpoints for the Blackwell autotune-restriction tests.
|
|
1366
|
+
|
|
1367
|
+
``kernel`` is what ``fla.ops.gated_delta_rule.wy_fast.prepare_wy_repr_bwd_kernel``
|
|
1368
|
+
resolves to (None = attribute absent). Returns (perf, removed, wy_fast_module).
|
|
1369
|
+
"""
|
|
1370
|
+
import importlib.util
|
|
1371
|
+
|
|
1372
|
+
from flash.engine.worker import perf
|
|
1373
|
+
|
|
1374
|
+
monkeypatch.setitem(sys.modules, "torch", _blackwell_torch(cc))
|
|
1375
|
+
monkeypatch.setattr(
|
|
1376
|
+
importlib.util,
|
|
1377
|
+
"find_spec",
|
|
1378
|
+
(lambda name: object()) if fla_present else (lambda name: None),
|
|
1379
|
+
raising=True,
|
|
1380
|
+
)
|
|
1381
|
+
wy = types.ModuleType("fla.ops.gated_delta_rule.wy_fast")
|
|
1382
|
+
if kernel is not None:
|
|
1383
|
+
wy.prepare_wy_repr_bwd_kernel = kernel
|
|
1384
|
+
pkg_fla = types.ModuleType("fla")
|
|
1385
|
+
pkg_ops = types.ModuleType("fla.ops")
|
|
1386
|
+
pkg_gdr = types.ModuleType("fla.ops.gated_delta_rule")
|
|
1387
|
+
pkg_fla.__path__, pkg_ops.__path__, pkg_gdr.__path__ = [], [], []
|
|
1388
|
+
pkg_gdr.wy_fast = wy
|
|
1389
|
+
for name, mod in (
|
|
1390
|
+
("fla", pkg_fla),
|
|
1391
|
+
("fla.ops", pkg_ops),
|
|
1392
|
+
("fla.ops.gated_delta_rule", pkg_gdr),
|
|
1393
|
+
("fla.ops.gated_delta_rule.wy_fast", wy),
|
|
1394
|
+
):
|
|
1395
|
+
monkeypatch.setitem(sys.modules, name, mod)
|
|
1396
|
+
removed: list[int] = []
|
|
1397
|
+
monkeypatch.setattr(
|
|
1398
|
+
perf, "_remove_fla_from_disk", lambda: (removed.append(1), (["/x/fla"], False))[1]
|
|
1399
|
+
)
|
|
1400
|
+
return perf, removed, wy
|
|
1401
|
+
|
|
1402
|
+
|
|
1403
|
+
def test_blackwell_gdn_autotune_restricted_to_validated_config(monkeypatch):
|
|
1404
|
+
"""sm100 + full upstream config space -> only num_warps=2/num_stages=4 survives; fla is KEPT.
|
|
1405
|
+
The tuner is wrapped in decorator layers, so the unwrap walk (.fn descent) is exercised too."""
|
|
1406
|
+
tuner = _FakeTuner([_TunerCfg(w, s) for w, s in _FULL_SPACE])
|
|
1407
|
+
perf, removed, _ = _patch_blackwell_stack(
|
|
1408
|
+
monkeypatch, kernel=_TunerWrapper(_TunerWrapper(tuner))
|
|
1409
|
+
)
|
|
1410
|
+
|
|
1411
|
+
perf._restrict_fla_gdn_autotune_on_blackwell()
|
|
1412
|
+
|
|
1413
|
+
assert [(c.num_warps, c.num_stages) for c in tuner.configs] == [(2, 4)]
|
|
1414
|
+
assert not removed, "restriction succeeded -> fla must be KEPT"
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
def test_blackwell_gdn_autotune_sm120_also_restricted(monkeypatch):
|
|
1418
|
+
"""Consumer Blackwell (sm120) matches upstream's IS_NVIDIA_BLACKWELL gate: restricted too."""
|
|
1419
|
+
tuner = _FakeTuner([_TunerCfg(w, s) for w, s in _FULL_SPACE])
|
|
1420
|
+
perf, removed, _ = _patch_blackwell_stack(monkeypatch, cc=(12, 0), kernel=tuner)
|
|
1421
|
+
|
|
1422
|
+
perf._restrict_fla_gdn_autotune_on_blackwell()
|
|
1423
|
+
|
|
1424
|
+
assert [(c.num_warps, c.num_stages) for c in tuner.configs] == [(2, 4)]
|
|
1425
|
+
assert not removed
|
|
1426
|
+
|
|
1427
|
+
|
|
1428
|
+
def test_blackwell_gdn_autotune_already_restricted_is_noop(monkeypatch):
|
|
1429
|
+
"""A pinned fla that already carries fla #1000 (space == validated config) is left alone —
|
|
1430
|
+
the guard must be a no-op on a future pin bump, not a second filter or a fail-closed."""
|
|
1431
|
+
tuner = _FakeTuner([_TunerCfg(2, 4)])
|
|
1432
|
+
perf, removed, _ = _patch_blackwell_stack(monkeypatch, kernel=tuner)
|
|
1433
|
+
|
|
1434
|
+
perf._restrict_fla_gdn_autotune_on_blackwell()
|
|
1435
|
+
|
|
1436
|
+
assert [(c.num_warps, c.num_stages) for c in tuner.configs] == [(2, 4)]
|
|
1437
|
+
assert not removed
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
|
+
def test_blackwell_gdn_autotune_fail_closed_when_tuner_missing(monkeypatch):
|
|
1441
|
+
"""Autotuner not found (fla layout changed, e.g. an unreviewed pin bump) -> fail CLOSED:
|
|
1442
|
+
fla is physically removed so transformers falls back to the pure-PyTorch delta rule."""
|
|
1443
|
+
perf, removed, _ = _patch_blackwell_stack(monkeypatch, kernel=None)
|
|
1444
|
+
|
|
1445
|
+
perf._restrict_fla_gdn_autotune_on_blackwell()
|
|
1446
|
+
|
|
1447
|
+
assert removed, "no autotuner -> must DISABLE fla (grad-correctness over speed)"
|
|
1448
|
+
|
|
1449
|
+
|
|
1450
|
+
def test_blackwell_gdn_autotune_fail_closed_when_no_validated_config(monkeypatch):
|
|
1451
|
+
"""The validated (2,4) config missing from the space -> nothing safe to run -> fail CLOSED."""
|
|
1452
|
+
tuner = _FakeTuner([_TunerCfg(4, 2), _TunerCfg(4, 3)])
|
|
1453
|
+
perf, removed, _ = _patch_blackwell_stack(monkeypatch, kernel=tuner)
|
|
1454
|
+
|
|
1455
|
+
perf._restrict_fla_gdn_autotune_on_blackwell()
|
|
1456
|
+
|
|
1457
|
+
assert removed, "no validated config in space -> must DISABLE fla"
|
|
1458
|
+
|
|
1459
|
+
|
|
1460
|
+
def test_blackwell_gdn_autotune_noop_without_fla(monkeypatch):
|
|
1461
|
+
"""fla absent (already the pure-PyTorch path) -> nothing to restrict, nothing to remove."""
|
|
1462
|
+
perf, removed, _ = _patch_blackwell_stack(monkeypatch, fla_present=False, kernel=None)
|
|
1463
|
+
|
|
1464
|
+
perf._restrict_fla_gdn_autotune_on_blackwell()
|
|
1465
|
+
|
|
1466
|
+
assert not removed
|
|
1467
|
+
|
|
1468
|
+
|
|
1469
|
+
def test_non_blackwell_gdn_autotune_untouched(monkeypatch):
|
|
1470
|
+
"""Hopper (sm90) keeps the full autotune space — the restriction is Blackwell-only (the
|
|
1471
|
+
tilelang fast path owns the sm90 story; shrinking its Triton space would only cost perf)."""
|
|
1472
|
+
tuner = _FakeTuner([_TunerCfg(w, s) for w, s in _FULL_SPACE])
|
|
1473
|
+
perf, removed, _ = _patch_blackwell_stack(monkeypatch, cc=(9, 0), kernel=tuner)
|
|
1474
|
+
|
|
1475
|
+
perf._restrict_fla_gdn_autotune_on_blackwell()
|
|
1476
|
+
|
|
1477
|
+
assert len(tuner.configs) == len(_FULL_SPACE)
|
|
1478
|
+
assert not removed
|
|
1479
|
+
|
|
1480
|
+
|
|
1481
|
+
# ---------------------------------------------------------------------------
|
|
1482
|
+
# sm100 tilelang GDN opt-out: the baked tilelang backend (needed for Hopper, fla
|
|
1483
|
+
# #640) computes WRONG GRADIENTS on B200/sm100 (measured: dq/dk ~0.72, dg ~1.28
|
|
1484
|
+
# rel-err at the production H==HV call shapes, deterministic, bf16 AND fp32) —
|
|
1485
|
+
# the root cause of the B200 35B-A3B SFT incident. The worker must opt fla out
|
|
1486
|
+
# via FLA_TILELANG=0 (upstream's own knob; upstream default-gates tilelang to
|
|
1487
|
+
# Hopper since fla #975) so fla dispatches to its Triton path, correct on sm100.
|
|
1488
|
+
# ---------------------------------------------------------------------------
|
|
1489
|
+
def _patch_arch(monkeypatch, cc):
|
|
1490
|
+
from flash.engine.worker import perf
|
|
1491
|
+
|
|
1492
|
+
monkeypatch.setitem(sys.modules, "torch", _blackwell_torch(cc))
|
|
1493
|
+
return perf
|
|
1494
|
+
|
|
1495
|
+
|
|
1496
|
+
def test_sm100_fla_tilelang_opted_out(monkeypatch):
|
|
1497
|
+
"""sm100 + FLA_TILELANG unset -> the worker sets FLA_TILELANG=0 before any fla dispatch."""
|
|
1498
|
+
import os
|
|
1499
|
+
|
|
1500
|
+
perf = _patch_arch(monkeypatch, (10, 0))
|
|
1501
|
+
monkeypatch.delenv("FLA_TILELANG", raising=False)
|
|
1502
|
+
|
|
1503
|
+
perf._force_fla_triton_gdn_on_sm100()
|
|
1504
|
+
|
|
1505
|
+
assert os.environ.get("FLA_TILELANG") == "0"
|
|
1506
|
+
|
|
1507
|
+
|
|
1508
|
+
def test_sm100_fla_tilelang_explicit_preset_wins(monkeypatch):
|
|
1509
|
+
"""An explicitly pre-set FLA_TILELANG (e.g. testing a fixed tilelang) is respected."""
|
|
1510
|
+
import os
|
|
1511
|
+
|
|
1512
|
+
perf = _patch_arch(monkeypatch, (10, 0))
|
|
1513
|
+
monkeypatch.setenv("FLA_TILELANG", "1")
|
|
1514
|
+
|
|
1515
|
+
perf._force_fla_triton_gdn_on_sm100()
|
|
1516
|
+
|
|
1517
|
+
assert os.environ.get("FLA_TILELANG") == "1"
|
|
1518
|
+
|
|
1519
|
+
|
|
1520
|
+
@pytest.mark.parametrize("cc", [(9, 0), (12, 0), (8, 9)])
|
|
1521
|
+
def test_non_sm100_fla_tilelang_untouched(monkeypatch, cc):
|
|
1522
|
+
"""sm90 NEEDS tilelang (fla #640); sm89/sm120 train healthily under the pin's default —
|
|
1523
|
+
the opt-out is strictly sm100 (the measured-broken arch)."""
|
|
1524
|
+
import os
|
|
1525
|
+
|
|
1526
|
+
perf = _patch_arch(monkeypatch, cc)
|
|
1527
|
+
monkeypatch.delenv("FLA_TILELANG", raising=False)
|
|
1528
|
+
|
|
1529
|
+
perf._force_fla_triton_gdn_on_sm100()
|
|
1530
|
+
|
|
1531
|
+
assert "FLA_TILELANG" not in os.environ
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/bake-kernel-cache.yml
RENAMED
|
File without changes
|
|
File without changes
|
{freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/main-source-guard.yml
RENAMED
|
File without changes
|
{freesolo_flash_dev-0.2.42 → freesolo_flash_dev-0.2.43}/.github/workflows/notify-tests-repo.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|