Skip to content

Conversation

charliermarsh
Copy link
Member

@charliermarsh charliermarsh commented Mar 9, 2025

Summary

This is a prototype that I'm considering shipping under --preview, based on light-the-torch.

light-the-torch patches pip to pull PyTorch packages from the PyTorch indexes automatically. And, in particular, light-the-torch will query the installed CUDA drivers to determine which indexes are compatible with your system.

This PR implements equivalent behavior under --torch-backend auto, though you can also set --torch-backend cpu, etc. for convenience. When enabled, the registry client will fetch from the appropriate PyTorch index when it sees a package from the PyTorch ecosystem (and ignore any other configured indexes, unless the package is explicitly pinned to a different index).

Right now, this is only implemented in the uv pip CLI, since it doesn't quite fit into the lockfile APIs given that it relies on feature detection on the currently-running machine.

Test Plan

On macOS, you can test this with (e.g.):

UV_TORCH_BACKEND=auto UV_CUDA_DRIVER_VERSION=450.80.2 cargo run \
  pip install torch --python-platform linux --python-version 3.12

On a GPU-enabled EC2 machine:

ubuntu@ip-172-31-47-149:~/uv$ UV_TORCH_BACKEND=auto cargo run pip install torch -v
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s
     Running `target/debug/uv pip install torch -v`
DEBUG uv 0.6.6 (e95ca063b 2025-03-14)
DEBUG Searching for default Python interpreter in virtual environments
DEBUG Found `cpython-3.13.0-linux-x86_64-gnu` at `/home/ubuntu/uv/.venv/bin/python3` (virtual environment)
DEBUG Using Python 3.13.0 environment at: .venv
DEBUG Acquired lock for `.venv`
DEBUG At least one requirement is not satisfied: torch
warning: The `--torch-backend` setting is experimental and may change without warning. Pass `--preview` to disable this warning.
DEBUG Detected CUDA driver version from `/sys/module/nvidia/version`: 550.144.3
...

@DEKHTIARJonathan
Copy link

DEKHTIARJonathan commented Mar 10, 2025

@charliermarsh : Adapted from a few different sources - namely conda.
Credit / Code Author: Michael Sarahan

I hope that illustrates my point better - why you need a plugin interface and you don't want to be the person responsible to maintain that 👍

# Copyright (C) 2012 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause
"""Detect CUDA version."""

import ctypes
import functools
import itertools
import multiprocessing
import os
import platform
from contextlib import suppress
from dataclasses import dataclass
from typing import Optional


@dataclass()
class CudaVersion:
    version: str
    architectures: list[str]


def cuda_version() -> Optional[CudaVersion]:
    # Do not inherit file descriptors and handles from the parent process.
    # The `fork` start method should be considered unsafe as it can lead to
    # crashes of the subprocess. The `spawn` start method is preferred.
    context = multiprocessing.get_context("spawn")
    queue = context.SimpleQueue()
    # Spawn a subprocess to detect the CUDA version
    detector = context.Process(
        target=_cuda_detector_target,
        args=(queue,),
        name="CUDA driver version detector",
        daemon=True,
    )
    try:
        detector.start()
        detector.join(timeout=60.0)
    finally:
        # Always cleanup the subprocess
        detector.kill()  # requires Python 3.7+

    if queue.empty():
        return None

    result = queue.get()
    if result:
        driver_version, architectures = result.split(";")
        result = CudaVersion(driver_version, architectures.split(","))
    return result


@functools.lru_cache(maxsize=None)
def cached_cuda_version():
    return cuda_version()


def _cuda_detector_target(queue):
    """
    Attempt to detect the version of CUDA present in the operating system in a
    subprocess.

    On Windows and Linux, the CUDA library is installed by the NVIDIA
    driver package, and is typically found in the standard library path,
    rather than with the CUDA SDK (which is optional for running CUDA apps).

    On macOS, the CUDA library is only installed with the CUDA SDK, and
    might not be in the library path.

    Returns: version string with CUDA version first, then a set of unique SM's for the GPUs present in the system
             (e.g., '12.4;8.6,9.0') or None if CUDA is not found.
             The result is put in the queue rather than a return value.
    """
    # Platform-specific libcuda location
    system = platform.system()
    if system == "Darwin":
        lib_filenames = [
            "libcuda.1.dylib",  # check library path first
            "libcuda.dylib",
            "/usr/local/cuda/lib/libcuda.1.dylib",
            "/usr/local/cuda/lib/libcuda.dylib",
        ]
    elif system == "Linux":
        lib_filenames = [
            "libcuda.so",  # check library path first
            "/usr/lib64/nvidia/libcuda.so",  # RHEL/Centos/Fedora
            "/usr/lib/x86_64-linux-gnu/libcuda.so",  # Ubuntu
            "/usr/lib/wsl/lib/libcuda.so",  # WSL
        ]
        # Also add libraries with version suffix `.1`
        lib_filenames = list(
            itertools.chain.from_iterable((f"{lib}.1", lib) for lib in lib_filenames)
        )
    elif system == "Windows":
        bits = platform.architecture()[0].replace("bit", "")  # e.g. "64" or "32"
        lib_filenames = [f"nvcuda{bits}.dll", "nvcuda.dll"]
    else:
        queue.put(None)  # CUDA not available for other operating systems
        return

    # Open library
    if system == "Windows":
        dll = ctypes.windll
    else:
        dll = ctypes.cdll
    for lib_filename in lib_filenames:
        with suppress(Exception):
            libcuda = dll.LoadLibrary(lib_filename)
            break
    else:
        queue.put(None)
        return

    # Empty `CUDA_VISIBLE_DEVICES` can cause `cuInit()` returns `CUDA_ERROR_NO_DEVICE`
    # Invalid `CUDA_VISIBLE_DEVICES` can cause `cuInit()` returns `CUDA_ERROR_INVALID_DEVICE`
    # Unset this environment variable to avoid these errors
    os.environ.pop("CUDA_VISIBLE_DEVICES", None)

    # Get CUDA version
    try:
        cuInit = libcuda.cuInit
        flags = ctypes.c_uint(0)
        ret = cuInit(flags)
        if ret != 0:
            queue.put(None)
            return

        cuDriverGetVersion = libcuda.cuDriverGetVersion
        version_int = ctypes.c_int(0)
        ret = cuDriverGetVersion(ctypes.byref(version_int))
        if ret != 0:
            queue.put(None)
            return

        # Convert version integer to version string
        value = version_int.value
        version_value = f"{value // 1000}.{(value % 1000) // 10}"

        count = ctypes.c_int(0)
        libcuda.cuDeviceGetCount(ctypes.pointer(count))

        architectures = set()
        for device in range(count.value):
            major = ctypes.c_int(0)
            minor = ctypes.c_int(0)
            libcuda.cuDeviceComputeCapability(
                ctypes.pointer(major),
                ctypes.pointer(minor),
                device)
            architectures.add(f"{major.value}.{minor.value}")
        queue.put(f"{version_value};{','.join(architectures)}")
    except Exception:
        queue.put(None)
        return

if __name__ == "__main__":
    print(cuda_version())

| "torchserve"
| "torchtext"
| "torchvision"
| "pytorch-triton"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add this list to some documentation? Reading the high-level overview I didn't realize we were hardcoding a package list.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we generate this by querying the PyTorch indices to see what they have? (Maybe a manually-run script that queries them and updates this list, or an automatically-run integration tests that makes sure this list is in sync with what's currently on their indices?)

Along those lines it would be helpful to have this list somewhere declarative. It might also be helpful to allow user-controlled overrides of this list if the set of packages changes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately I don't know that we can... We don't want all packages on these indexes, because they include things like jinja2. And in some cases, they include incomplete packages like markupsafe (where they only have a few wheels).

Copy link
Collaborator

@geofft geofft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a great idea.

Would it be worth naming this feature something like uv-specialized-index instead of uv-torch with an eye to extending it to other libraries in the future? (jaxlib and tensorflow, for instance, have current/popular versions on PyPI, but I think also have their own indees)?

| "torchserve"
| "torchtext"
| "torchvision"
| "pytorch-triton"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we generate this by querying the PyTorch indices to see what they have? (Maybe a manually-run script that queries them and updates this list, or an automatically-run integration tests that makes sure this list is in sync with what's currently on their indices?)

Along those lines it would be helpful to have this list somewhere declarative. It might also be helpful to allow user-controlled overrides of this list if the set of packages changes.

@samypr100
Copy link
Collaborator

I think this is a great idea.

Would it be worth naming this feature something like uv-specialized-index instead of uv-torch with an eye to extending it to other libraries in the future? (jaxlib and tensorflow, for instance, have current/popular versions on PyPI, but I think also have their own indees)?

I had a similar thought, I think this is one of many cases. Also considering when such indexes are mirrored or vendored internally. I was thinking what would be the right naming. I know some avenues refers to this as a suffixed index, so maybe uv-suffixed-index? Same with --torch-backend, maybe something more generic of it's intent would be more future proof, such as --index-suffix

@samypr100
Copy link
Collaborator

samypr100 commented Mar 12, 2025

though I don't remember off hand whether NVIDIA's license allows redistributing it

iirc this is no longer an issue with the new open source drivers (e.g. nvidia-driver-{ver}-open)

Nevermind, didn't notice you were referring to CUDA.

I think we should get this via /sys/module/nvidia/version

💯 In my experience nvidia-smi can also take a long time depending on gpu load.

Although there multiple locations depending on how (e.g. dkms) and environment (windows, osx) it's installed. For example, WSL 2 its even weirder due to the shared drivers with the host situation. So nvidia-smi might be the most sure-fire low risk way (assuming no issues with install).

@charliermarsh
Copy link
Member Author

Definitely agree with moving this out of the interpreter query (and possibly reading it from outside nvidia-smi -- I need to do some research).

I'm a little wary of trying to brand this as something more general than torch, because I'll likely want to reconsider the mechanism and design entirely as we generalize it. So it seems nice to keep it as an experimental torch-specific feature, then modify it as we generalize.

@charliermarsh charliermarsh force-pushed the charlie/ltt branch 2 times, most recently from 10ecfd8 to 3349921 Compare March 15, 2025 02:21
@charliermarsh charliermarsh requested review from geofft and konstin March 15, 2025 02:21
@charliermarsh
Copy link
Member Author

@konstin @geofft -- I believe I've addressed all feedback: we now query from /sys/module/nvidia/version and fall back to nvidia-smi; and all the accelerator stuff is decoupled from the Python interpreter (and no longer cached).

@charliermarsh charliermarsh force-pushed the charlie/ltt branch 2 times, most recently from 96038e9 to c9e4b20 Compare March 15, 2025 02:28
Copy link
Member

@konstin konstin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deferring to @geofft for the new detect logic

Comment on lines +70 to +72
Ok(None) => {
debug!("Failed to parse CUDA driver version from `/proc/driver/nvidia/version`");
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this case return an error instead of falling through to nvidia-smi?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not confident enough in the format of this one... It seems like it varies across machines.

Comment on lines +86 to +90
if output.status.success() {
let driver_version = Version::from_str(&String::from_utf8(output.stdout)?)?;
debug!("Detected CUDA driver version from `nvidia-smi`: {driver_version}");
return Ok(Some(Self::Cuda { driver_version }));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else {debug!("nvidia-smi returned error {output.status}: {output.stderr}")} might be nice

@charliermarsh charliermarsh force-pushed the charlie/ltt branch 3 times, most recently from 14cb5ed to 9e40e0c Compare March 19, 2025 14:26
@charliermarsh charliermarsh enabled auto-merge (squash) March 19, 2025 14:29
@charliermarsh charliermarsh merged commit 5173b59 into main Mar 19, 2025
89 checks passed
@charliermarsh charliermarsh deleted the charlie/ltt branch March 19, 2025 14:37
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Mar 24, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [astral-sh/uv](https://github.com/astral-sh/uv) | patch | `0.6.5` -> `0.6.9` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>astral-sh/uv (astral-sh/uv)</summary>

### [`v0.6.9`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#069)

[Compare Source](astral-sh/uv@0.6.8...0.6.9)

##### Enhancements

-   Use `keyring --mode creds` when `authenticate = "always"` ([#&#8203;12316](astral-sh/uv#12316))
-   Fail with specific error message when no password is present and `authenticate = "always"` ([#&#8203;12313](astral-sh/uv#12313))

##### Bug fixes

-   Add boolish value parser for `UV_MANAGED_PYTHON` flags ([#&#8203;12345](astral-sh/uv#12345))
-   Make deserialization non-fatal when assessing source tree revisions ([#&#8203;12319](astral-sh/uv#12319))
-   Use resolver-returned wheel over alternate cached wheel ([#&#8203;12301](astral-sh/uv#12301))

##### Documentation

-   Add experimental `--torch-backend` to the PyTorch guide ([#&#8203;12317](astral-sh/uv#12317))
-   Fix `#keyring-provider` references in alternative index docs ([#&#8203;12315](astral-sh/uv#12315))
-   Fix `--directory` path in examples ([#&#8203;12165](astral-sh/uv#12165))

##### Preview changes

-   Automatically infer the PyTorch index via `--torch-backend=auto` ([#&#8203;12070](astral-sh/uv#12070))

### [`v0.6.8`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#068)

[Compare Source](astral-sh/uv@0.6.7...0.6.8)

##### Enhancements

-   Add support for enabling all groups by default with `default-groups = "all"` ([#&#8203;12289](astral-sh/uv#12289))
-   Add simpler `--managed-python` and `--no-managed-python` flags for toggling Python preferences ([#&#8203;12246](astral-sh/uv#12246))

##### Performance

-   Avoid allocations for default cache keys ([#&#8203;12063](astral-sh/uv#12063))

##### Bug fixes

-   Allow local version mismatches when validating lockfile ([#&#8203;12285](astral-sh/uv#12285))
-   Allow owned string when deserializing `requires-python` ([#&#8203;12278](astral-sh/uv#12278))
-   Make cache errors non-fatal in `Planner::build` ([#&#8203;12281](astral-sh/uv#12281))

### [`v0.6.7`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#067)

[Compare Source](astral-sh/uv@0.6.6...0.6.7)

##### Python

-   Add CPython 3.14.0a6
-   Fix regression where extension modules would use wrong `CXX` compiler on Linux
-   Enable FTS3 enhanced query syntax for SQLite

See the [`python-build-standalone` release notes](https://github.com/astral-sh/python-build-standalone/releases/tag/20250317) for more details.

##### Enhancements

-   Add support for `-c` constraints in `uv add` ([#&#8203;12209](astral-sh/uv#12209))
-   Add support for `--global` default version in `uv python pin` ([#&#8203;12115](astral-sh/uv#12115))
-   Always reinstall local source trees passed to `uv pip install` ([#&#8203;12176](astral-sh/uv#12176))
-   Render token claims on publish permission error ([#&#8203;12135](astral-sh/uv#12135))
-   Add pip-compatible `--group` flag to `uv pip install` and `uv pip compile` ([#&#8203;11686](astral-sh/uv#11686))

##### Preview features

-   Avoid creating duplicate directory entries in built wheels ([#&#8203;12206](astral-sh/uv#12206))
-   Allow overriding module names for editable builds ([#&#8203;12137](astral-sh/uv#12137))

##### Performance

-   Avoid replicating core-metadata field on `File` struct ([#&#8203;12159](astral-sh/uv#12159))

##### Bug fixes

-   Add `src` to default cache keys ([#&#8203;12062](astral-sh/uv#12062))
-   Discard insufficient fork markers ([#&#8203;10682](astral-sh/uv#10682))
-   Ensure `python pin --global` creates parent directories if missing ([#&#8203;12180](astral-sh/uv#12180))
-   Fix GraalPy abi tag parsing and discovery ([#&#8203;12154](astral-sh/uv#12154))
-   Remove extraneous script packages in `uv sync --script` ([#&#8203;12158](astral-sh/uv#12158))
-   Remove redundant `activate.bat` output ([#&#8203;12160](astral-sh/uv#12160))
-   Avoid subsequent index hint when no versions are available on the first index ([#&#8203;9332](astral-sh/uv#9332))
-   Error on lockfiles with incoherent wheel versions ([#&#8203;12235](astral-sh/uv#12235))

##### Rust API

-   Update `BaseClientBuild` to accept custom proxies ([#&#8203;12232](astral-sh/uv#12232))

##### Documentation

-   Make testpypi index explicit in example snippet ([#&#8203;12148](astral-sh/uv#12148))
-   Reverse and format the archived changelogs ([#&#8203;12099](astral-sh/uv#12099))
-   Use consistent commas around i.e. and e.g. ([#&#8203;12157](astral-sh/uv#12157))
-   Fix typos in MRE docs ([#&#8203;12198](astral-sh/uv#12198))
-   Fix double space typo ([#&#8203;12171](astral-sh/uv#12171))

### [`v0.6.6`](https://github.com/astral-sh/uv/blob/HEAD/CHANGELOG.md#066)

[Compare Source](astral-sh/uv@0.6.5...0.6.6)

##### Python

-   Add support for dynamic musl Python distributions on x86-64 Linux ([#&#8203;12121](astral-sh/uv#12121))
-   Allow the experimental JIT to be enabled at runtime on Python 3.13 and 3.14 on Linux
-   Upgrade the build toolchain to LLVM 20, improving performance

See the [`python-build-standalone` release notes](https://github.com/astral-sh/python-build-standalone/releases/tag/20250311) for more details.

##### Enhancements

-   Add `--marker` flag to `uv add` ([#&#8203;12012](astral-sh/uv#12012))
-   Allow overriding module name for uv build backend ([#&#8203;11884](astral-sh/uv#11884))
-   Sync latest Python releases ([#&#8203;12120](astral-sh/uv#12120))
-   Use 'Upload' instead of 'Download' in publish reporter ([#&#8203;12029](astral-sh/uv#12029))
-   Add `[index].authenticate` allowing authentication to be required on an index ([#&#8203;11896](astral-sh/uv#11896))
-   Add support for Windows legacy scripts in `uv tool run` ([#&#8203;12079](astral-sh/uv#12079))
-   Propagate conflicting dependency groups when using `include-group` ([#&#8203;12005](astral-sh/uv#12005))
-   Show ambiguous requirements when `uv add` failed ([#&#8203;12106](astral-sh/uv#12106))

##### Performance

-   Cache workspace discovery ([#&#8203;12096](astral-sh/uv#12096))
-   Insert dependencies into fork state prior to fetching metadata ([#&#8203;12057](astral-sh/uv#12057))
-   Remove some allocations from `uv-auth` ([#&#8203;12077](astral-sh/uv#12077))

##### Bug fixes

-   Avoid considering `PATH` updated when the `export` is commented in the shellrc ([#&#8203;12043](astral-sh/uv#12043))
-   Fix `uv publish` retry on network failures ([#&#8203;12041](astral-sh/uv#12041))
-   Use a sized stream in `uv publish` to comply with WSGI PyPI server constraints ([#&#8203;12111](astral-sh/uv#12111))
-   Fix `uv python install --reinstall` when the version was not previously installed ([#&#8203;12124](astral-sh/uv#12124))

##### Preview features

-   Fix `uv_build` invocation ([#&#8203;12058](astral-sh/uv#12058))

##### Documentation

-   Quote versions string in `python-versions.md` ([#&#8203;12112](astral-sh/uv#12112))
-   Fix tool concept page headings ([#&#8203;12053](astral-sh/uv#12053))
-   Update the `[index].authenticate` docs ([#&#8203;12102](astral-sh/uv#12102))
-   Update versioning policy ([#&#8203;11666](astral-sh/uv#11666))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xOTQuMCIsInVwZGF0ZWRJblZlciI6IjM5LjIwOS4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Apr 21, 2025
## 0.6.14

### Python versions

The following Python versions have been added:

- CPython 3.13.3
- CPython 3.12.10
- CPython 3.11.12
- CPython 3.10.17
- CPython 3.9.22

See the [`python-build-standalone` release notes](https://github.com/astral-sh/python-build-standalone/releases/tag/20250409) for more details.

### Enhancements

- Add `uv-build` and `uv_build` aliases to `uv init --build-backend` ([#12776](astral-sh/uv#12776))
- Emit dedicated error message for Conda `environment.yml` files ([#12669](astral-sh/uv#12669))


### Preview features

- Build backend: Check module dir exists for sdist build ([#12779](astral-sh/uv#12779))
- Build backend: Fix sdist with long directories ([#12764](astral-sh/uv#12764))

### Performance

- Avoid querying GitHub on repeated install invocations ([#12767](astral-sh/uv#12767))

### Bug fixes

- Error when `tool.uv.sources` is set in system-level configuration file ([#12757](astral-sh/uv#12757))
- Split workspace members onto their own lines in `uv init` ([#12756](astral-sh/uv#12756))

### Documentation

- Add lockfile note about PEP 751 ([#12732](astral-sh/uv#12732))
- Extend the reference documentation for `uv pip sync` ([#12683](astral-sh/uv#12683))
- Fix mismatched pip interface header / nav titles ([#12640](astral-sh/uv#12640))

## 0.6.13

### Enhancements

- Add `--show-version` to `uv python find` ([#12376](astral-sh/uv#12376))
- Remove `--no-config` warning from `uv pip compile` and `uv pip sync` ([#12642](astral-sh/uv#12642))
- Skip repeated directories in `PATH` when searching for Python interpreters ([#12367](astral-sh/uv#12367))
- Unset `SCRIPT_PATH` in relocatable activation script ([#12672](astral-sh/uv#12672))
- Add `UV_PYTHON_DOWNLOADS_JSON_URL` to set custom managed python sources ([#10939](astral-sh/uv#10939))
- Reject `pyproject.toml` files in `uv pip compile -o` ([#12673](astral-sh/uv#12673))
- Respect the `--offline` flag for Git operations ([#12619](astral-sh/uv#12619))

### Bug fixes

- Warn instead of error if CRC appears to be missing ([#12722](astral-sh/uv#12722))
- Avoid infinite loop in `uv export` with conflicts ([#12726](astral-sh/uv#12726))

### Rust API

- Update MSRV to 1.84 ([#12670](astral-sh/uv#12670))

## 0.6.12

### Enhancements

- Report the queried executable path in `uv python list` ([#12628](astral-sh/uv#12628))
- Improve archive unpack error messages ([#12627](astral-sh/uv#12627))

### Bug fixes

- Respect `authenticate` when using `explicit = true` ([#12631](astral-sh/uv#12631))
- Normalize extra and group names in `uv add` and `uv remove` ([#12586](astral-sh/uv#12586))
- Enforce CRC-32 checks when unpacking archives ([#12623](astral-sh/uv#12623))
- Fix parsing of `python-platform` in settings files ([#12592](astral-sh/uv#12592))

### Documentation

- Add note about `uv build` to `package = false` ([#12608](astral-sh/uv#12608))
- Add index fallback note to `authenticate = always` documentation ([#12498](astral-sh/uv#12498))
- Fix invalid 'kind' reference in flat index docs ([#12583](astral-sh/uv#12583))

## 0.6.11

### Enhancements

- Add dependents ("via ..." comments) in `uv export` command ([#12350](astral-sh/uv#12350))
- Bump least-recent non-EOL macOS version to 13.0 ([#12518](astral-sh/uv#12518))
- Support `--find-links`-style "flat" indexes in `[[tool.uv.index]]` ([#12407](astral-sh/uv#12407))
- Distinguish between `-q` and `-qq` ([#12300](astral-sh/uv#12300))

### Configuration

- Support `UV_PROJECT` environment to set project directory. ([#12327](astral-sh/uv#12327))

### Performance

- Use a boxed slice for various requirement types ([#12514](astral-sh/uv#12514))

### Bug fixes

- Add a newline after metadata when initializing scripts with other metadata blocks ([#12501](astral-sh/uv#12501))
- Avoid writing empty `requires-python` to script blocks ([#12517](astral-sh/uv#12517))
- Respect build constraints in `uv sync` ([#12502](astral-sh/uv#12502))
- Respect transitive dependencies in `uv tree --only-group` ([#12560](astral-sh/uv#12560))

## 0.6.10

### Enhancements

- Add `uv sync --check` flag ([#12342](astral-sh/uv#12342))
- Add support for Python version requests in `uv python list` ([#12375](astral-sh/uv#12375))
- Support `.env` files in `uv tool run` ([#12386](astral-sh/uv#12386))
- Support `python find --script` ([#11891](astral-sh/uv#11891))

### Preview features

- Check all compatible torch indexes when `--torch-backend` is enabled ([#12385](astral-sh/uv#12385))

### Performance

- Use a boxed slice for extras and groups ([#12391](astral-sh/uv#12391))
- Use small string for index name type ([#12355](astral-sh/uv#12355))

### Bug fixes

- Allow virtual packages with `--no-build` ([#12314](astral-sh/uv#12314))
- Ignore `--find-links` entries for pinned indexes ([#12396](astral-sh/uv#12396))
- Omit wheels from lockfile based on `--exclude-newer` ([#12299](astral-sh/uv#12299))
- Retain end-of-line comment position when adding dependency ([#12360](astral-sh/uv#12360))
- Omit fragment when querying for wheels in Simple HTML API ([#12384](astral-sh/uv#12384))
- Error on missing argument in `requirements.txt` ([#12354](astral-sh/uv#12354))
- Support modules with different casing in build backend ([#12240](astral-sh/uv#12240))
- Add authentication policy support for `pip` commands ([#12470](astral-sh/uv#12470))

## 0.6.9

### Enhancements

- Use `keyring --mode creds` when `authenticate = "always"` ([#12316](astral-sh/uv#12316))
- Fail with specific error message when no password is present and `authenticate = "always"` ([#12313](astral-sh/uv#12313))

### Bug fixes

- Add boolish value parser for `UV_MANAGED_PYTHON` flags ([#12345](astral-sh/uv#12345))
- Make deserialization non-fatal when assessing source tree revisions ([#12319](astral-sh/uv#12319))
- Use resolver-returned wheel over alternate cached wheel ([#12301](astral-sh/uv#12301))

### Documentation

- Add experimental `--torch-backend` to the PyTorch guide ([#12317](astral-sh/uv#12317))
- Fix `#keyring-provider` references in alternative index docs ([#12315](astral-sh/uv#12315))
- Fix `--directory` path in examples ([#12165](astral-sh/uv#12165))

### Preview changes

- Automatically infer the PyTorch index via `--torch-backend=auto` ([#12070](astral-sh/uv#12070))

## 0.6.8

### Enhancements

- Add support for enabling all groups by default with `default-groups = "all"` ([#12289](astral-sh/uv#12289))
- Add simpler `--managed-python` and `--no-managed-python` flags for toggling Python preferences ([#12246](astral-sh/uv#12246))

### Performance

- Avoid allocations for default cache keys ([#12063](astral-sh/uv#12063))

### Bug fixes

- Allow local version mismatches when validating lockfile ([#12285](astral-sh/uv#12285))
- Allow owned string when deserializing `requires-python` ([#12278](astral-sh/uv#12278))
- Make cache errors non-fatal in `Planner::build` ([#12281](astral-sh/uv#12281))

## 0.6.7

### Python

- Add CPython 3.14.0a6
- Fix regression where extension modules would use wrong `CXX` compiler on Linux
- Enable FTS3 enhanced query syntax for SQLite

See the [`python-build-standalone` release notes](https://github.com/astral-sh/python-build-standalone/releases/tag/20250317) for more details.

### Enhancements

- Add support for `-c` constraints in `uv add` ([#12209](astral-sh/uv#12209))
- Add support for `--global` default version in `uv python pin` ([#12115](astral-sh/uv#12115))
- Always reinstall local source trees passed to `uv pip install` ([#12176](astral-sh/uv#12176))
- Render token claims on publish permission error ([#12135](astral-sh/uv#12135))
- Add pip-compatible `--group` flag to `uv pip install` and `uv pip compile` ([#11686](astral-sh/uv#11686))

### Preview features

- Avoid creating duplicate directory entries in built wheels ([#12206](astral-sh/uv#12206))
- Allow overriding module names for editable builds ([#12137](astral-sh/uv#12137))

### Performance

- Avoid replicating core-metadata field on `File` struct ([#12159](astral-sh/uv#12159))

### Bug fixes

- Add `src` to default cache keys ([#12062](astral-sh/uv#12062))
- Discard insufficient fork markers ([#10682](astral-sh/uv#10682))
- Ensure `python pin --global` creates parent directories if missing ([#12180](astral-sh/uv#12180))
- Fix GraalPy abi tag parsing and discovery ([#12154](astral-sh/uv#12154))
- Remove extraneous script packages in `uv sync --script` ([#12158](astral-sh/uv#12158))
- Remove redundant `activate.bat` output ([#12160](astral-sh/uv#12160))
- Avoid subsequent index hint when no versions are available on the first index ([#9332](astral-sh/uv#9332))
- Error on lockfiles with incoherent wheel versions ([#12235](astral-sh/uv#12235))

### Rust API

- Update `BaseClientBuild` to accept custom proxies ([#12232](astral-sh/uv#12232))

### Documentation

- Make testpypi index explicit in example snippet ([#12148](astral-sh/uv#12148))
- Reverse and format the archived changelogs ([#12099](astral-sh/uv#12099))
- Use consistent commas around i.e. and e.g. ([#12157](astral-sh/uv#12157))
- Fix typos in MRE docs ([#12198](astral-sh/uv#12198))
- Fix double space typo ([#12171](astral-sh/uv#12171))
Copy link

@coezbek coezbek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--torch-backend=auto fails for multiple GPU systems which don't have /sys/module/nvidia/version or /proc/driver/nvidia/version (e.g. WSL)

.output()
{
if output.status.success() {
let driver_version = Version::from_str(&String::from_utf8(output.stdout)?)?;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a system with multiple GPUs this line will return multiple driver versions, e.g. on my system:

$ nvidia-smi --query-gpu=driver_version --format=csv,noheader
572.60
572.60

This will make uv pip install with --torch-backend=auto fail with the following error:

uv pip install -U "vllm[audio]" --torch-backend=auto
error: after parsing `572.60
`, found `572.60
`, which is not part of a valid version

nvidia-smi does not respect NVIDIA_VISIBLE_DEVICES, so there is no way from the outside to use --torch-backend=auto with two graphics cards at the moment.

Workaround is to run nvidia-smi, identify CUDA version there and run with --torch-backend=cuXXX as indicated by nvidia-smi.

@DEKHTIARJonathan
Copy link

@charliermarsh I recommend you to use nvml - that's what we decided to use for the variant plugin.
It's guaranteed to be present if the driver is installed

Example:
https://github.com/wheelnext/nvidia-variant-provider/blob/dev/nvidia_variant_provider/detect_cuda.py

This is using the Python bindings - but NVML is C library you can directly dlopen. The python example should tell you what functions to call for SM, UMD and KMD ;)

@charliermarsh
Copy link
Member Author

Awesome, thanks @DEKHTIARJonathan. I filed an issue here: #14664

@hamzaq2000
Copy link

hamzaq2000 commented Jul 18, 2025

Tested the following command on a system with a GTX 1080 Ti and CUDA 12.8 driver (what shows in nvidia-smi) installed.

uv pip install torch --torch-backend=auto --preview

Then ran this test script:

import torch
tensor = torch.randn(3, 4, device='cuda')
print(tensor)

And got this:

  cpu = _conversion_method_template(device=torch.device("cpu"))
/root/env/lib/python3.11/site-packages/torch/cuda/__init__.py:262: UserWarning:
    Found GPU0 NVIDIA GeForce GTX 1080 Ti which is of cuda capability 6.1.
    PyTorch no longer supports this GPU because it is too old.
    The minimum cuda capability supported by this library is 7.5.

  warnings.warn(
/root/env/lib/python3.11/site-packages/torch/cuda/__init__.py:287: UserWarning:
NVIDIA GeForce GTX 1080 Ti with CUDA capability sm_61 is not compatible with the current PyTorch installation.
The current PyTorch install supports CUDA capabilities sm_75 sm_80 sm_86 sm_90 sm_100 sm_120 compute_120.
If you want to use the NVIDIA GeForce GTX 1080 Ti GPU with PyTorch, please check the instructions at https://pytorch.org/get-started/locally/

  warnings.warn(
Traceback (most recent call last):
  File "/root/torch_test.py", line 4, in <module>
    tensor = torch.randn(3, 4, device='cuda')
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: CUDA error: no kernel image is available for execution on the device
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1
Compile with `TORCH_USE_CUDA_DSA` to enable device-side assertions.

I think just looking at the installed CUDA version/driver might not be enough, the CUDA compute capability supported by different torch versions is of relevance as well. In this case, a GTX 1080 Ti has drivers installed that show CUDA 12.8 in nvidia-smi but we can't actually use the cu128 torch wheel, which --torch-backend=auto installs, as it doesn't support GPUs with CUDA compute capability < 7.5.

Some relevant discussion I found:
https://discuss.pytorch.org/t/gpu-compute-capability-support-for-each-pytorch-version/62434/4
https://github.com/moi90/pytorch_compute_capabilities

I then also tested without --torch-backend=auto, so simply:

uv pip install torch

This seems to install the cu126 wheel, and with this the test script worked just fine, meaning the cu126 wheel has not yet dropped support for CUDA compute capability 6.1 devices.

@charliermarsh
Copy link
Member Author

Do you mind filing a separate issue? We tend to prefer that over commenting on closed issues or pull requests.

@DEKHTIARJonathan
Copy link

DEKHTIARJonathan commented Jul 18, 2025

@hamzaq2000

a GTX 1080 Ti has drivers installed that show CUDA 12.8 in nvidia-smi but we can't actually use the cu128 torch wheel, which --torch-backend=auto installs, as it doesn't support GPUs with CUDA compute capability < 7.5.

It's not entirely accurate. It's deprecated starting from CUDA 12.8 but not incompatible (otherwise you wouldn't have been to install it).
What happens is that PyTorch stopped building SM < 7.5 with their newer releases.

I don't think @charliermarsh can fix it without having a massive headache of if/else conditions (it's on a per-library/package basis). @hamzaq2000 Just install CUDA 12.6, it won't be of any use to you to be on a newer release and you won't stumble into such issues ;)

@hamzaq2000
Copy link

@charliermarsh

Do you mind filing a separate issue? We tend to prefer that over commenting on closed issues or pull requests.

Certainly, sorry about that! #14742

@DEKHTIARJonathan

Unfortunately I'm not knowledgeable enough to comment on the feasibility of this, so I won't. But I thought it was worth putting out there; hopefully it is fixable and --torch-backend=auto can cleanly install the the correct torch wheel from the correct index for all NVIDIA GPUs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-build Disable building binaries in CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants