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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/source/builder-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Initialize a new kernel project from template

Default value: `Apache-2.0`
* `--name <OWNER/REPO>` — Name of the kernel repo (e.g. `drbh/my-kernel`)
* `--backends <BACKENDS>` — Backends to enable (`all`, `cpu`, `cuda`, `metal`, `neuron`, `rocm`, `xpu`)
* `--backends <BACKENDS>` — Backends to enable (`all`, `cpu`, `cuda`, `metal`, `neuron`, `rocm`, `tpu`, `xpu`)

* `--overwrite` — Overwrite existing scaffold files (preserves other files)

Expand Down
5 changes: 5 additions & 0 deletions docs/source/builder/build-variants.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ available. This list will be updated as new PyTorch versions are released.
- `torch213-cxx11-rocm71-x86_64-linux`
- `torch213-cxx11-rocm72-x86_64-linux`

## TPU x86_64-linux

- `torch-tpu`

## XPU x86_64-linux

- `torch211-cxx11-xpu20253-x86_64-linux`
Expand All @@ -77,4 +81,5 @@ one or more of the following variants:
- `torch-cuda`
- `torch-metal`
- `torch-rocm`
- `torch-tpu`
- `torch-xpu`
2 changes: 1 addition & 1 deletion docs/source/kernel-requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ The `backend` specifies a dictionary of the following form:
```

The backend `type` must be one of `cann`, `cpu`, `cuda`, `metal`, `neuron`,
`rocm`, or `xpu`. For CUDA and ROCm, the supported architectures must
`rocm`, `tpu`, or `xpu`. For CUDA and ROCm, the supported architectures must
be specified in the `archs` field.

### Python dependencies
Expand Down
61 changes: 61 additions & 0 deletions examples/kernels/relu-tpu/CARD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
library_name: kernels
{% if license %}license: {{ license }}
{% endif %}---

This is the repository card of {{ repo_id }} that has been pushed on the Hub. It was built to be used with the [`kernels` library](https://github.com/huggingface/kernels). This card was automatically generated.

## How to use
{% if functions %}

```python
# make sure `kernels` is installed: `pip install -U kernels`
from kernels import get_kernel

kernel_module = get_kernel("{{ repo_id }}", version={{ version }})
{{ functions[0] }} = kernel_module.{{ functions[0] }}

{{ functions[0] }}(...)
```
{% else %}

Usage example not available.
{% endif %}

## Available functions
{% if functions %}
{% for func in functions %}
- `{{ func }}`
{% endfor %}
{% else %}

Function list not available.
{% endif %}
{% if layers %}

## Available layers
{% for layer in layers %}
- `{{ layer }}`
{% endfor %}
{% endif %}

## Benchmarks
{% if has_benchmark %}

Benchmarking script is available for this kernel. Run `kernels benchmark {{ repo_id }} --version {{ version }}`.
{% else %}

No benchmark available yet.
{% endif %}
{% if upstream %}

## Upstream

The original source code for this kernel comes from {{ upstream }}.
{% endif %}
{% if source %}

## Source

The kernel-builder formatted source for this kernel is available at {{ source }}.
{% endif %}
16 changes: 16 additions & 0 deletions examples/kernels/relu-tpu/build.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[general]
name = "relu-tpu"
version = 1
edition = 5
license = "Apache-2.0"
backends = ["tpu"]

[general.hub]
repo-id = "kernels-test/relu-tpu"

[general.tpu]
python-depends = ["torch_tpu", "jax"]

[torch-noarch]

[kernel]
17 changes: 17 additions & 0 deletions examples/kernels/relu-tpu/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
description = "Flake for TPU ReLU kernel";

inputs = {
kernel-builder.url = "path:../../..";
};

outputs =
{
self,
kernel-builder,
}:
kernel-builder.lib.genKernelFlakeOutputs {
inherit self;
path = ./.;
};
}
14 changes: 14 additions & 0 deletions examples/kernels/relu-tpu/torch-ext/relu_tpu/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import jax
import jax.numpy as jnp
from torch_tpu._internal.pallas import jax_op


def _jax_relu(x: jax.Array) -> jax.Array:
return jnp.maximum(x, 0)


relu = jax_op("relu_tpu::relu", _jax_relu)

from . import layers # noqa: E402

__all__ = ["layers", "relu"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import torch
import torch.nn as nn

from .. import relu


class ReLU(nn.Module):
def forward(self, x: torch.Tensor) -> torch.Tensor:
return relu(x)
2 changes: 1 addition & 1 deletion kernel-builder/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub struct InitArgs {
#[arg(long, value_name = "OWNER/REPO")]
pub name: Option<RepoInfo>,

/// Backends to enable (`all`, `cpu`, `cuda`, `metal`, `neuron`, `rocm`, `xpu`).
/// Backends to enable (`all`, `cpu`, `cuda`, `metal`, `neuron`, `rocm`, `tpu`, `xpu`).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if we want to add support to initialize a tpu repo, I think we need to update build_init_fileset to handle has_tpu and render a tpu/noarch scaffold, including [general.tpu], [torch-noarch], and a tpu-specific Python module template. (similar to the other backends). otherwise we should probably leave it out of this list

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Slightly related: neuron is already in that list and also has no has_neuron or template. Maybe we should remove it from here.

#[arg(long, num_args = 1.., default_values_t = default_init_backends())]
pub backends: Vec<BackendSelection>,

Expand Down
8 changes: 7 additions & 1 deletion kernel-builder/src/pyproject/templates/torch/noarch/_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ def get_backend() -> str:
"""Detect the backend by inspecting torch."""
import torch

if hasattr(torch, "neuron"):
if hasattr(torch.backends, "tpu"):
# torch_tpu sets torch.backends.tpu when it is imported (via
# torch's device-backend autoload), regardless of whether TPU
# hardware is present — analogous to torch.version.cuda being
# set on CUDA builds without a GPU.
return "tpu"
elif hasattr(torch, "neuron"):
# Needs to be sorted before specific Torch builds, since Neuron
# extension can be loaded into e.g. CUDA Torch builds.
return "neuron"
Expand Down
3 changes: 2 additions & 1 deletion kernels-data/bindings/python/kernels_data.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class Backend(Enum):
Metal = "Metal"
Neuron = "Neuron"
ROCm = "ROCm"
TPU = "TPU"
XPU = "XPU"

@staticmethod
Expand All @@ -40,7 +41,7 @@ class Backend(Enum):

Args:
s: One of `"cann"`, `"cpu"`, `"cuda"`, `"metal"`,
`"neuron"`, `"rocm"`, `"xpu"`.
`"neuron"`, `"rocm"`, `"tpu"`, `"xpu"`.

Raises:
ValueError: If the backend name is unknown.
Expand Down
7 changes: 6 additions & 1 deletion kernels-data/bindings/python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ enum PyBackend {
Neuron,
#[pyo3(name = "ROCm")]
Rocm,
#[pyo3(name = "TPU")]
Tpu,
#[pyo3(name = "XPU")]
Xpu,
}
Expand All @@ -101,6 +103,7 @@ impl From<Backend> for PyBackend {
Backend::Metal => PyBackend::Metal,
Backend::Neuron => PyBackend::Neuron,
Backend::Rocm => PyBackend::Rocm,
Backend::Tpu => PyBackend::Tpu,
Backend::Xpu => PyBackend::Xpu,
}
}
Expand All @@ -115,6 +118,7 @@ impl From<PyBackend> for Backend {
PyBackend::Metal => Backend::Metal,
PyBackend::Neuron => Backend::Neuron,
PyBackend::Rocm => Backend::Rocm,
PyBackend::Tpu => Backend::Tpu,
PyBackend::Xpu => Backend::Xpu,
}
}
Expand All @@ -123,7 +127,7 @@ impl From<PyBackend> for Backend {
#[pymethods]
impl PyBackend {
/// Parse a backend name (`"cann"`, `"cpu"`, `"cuda"`, `"metal"`,
/// `"neuron"`, `"rocm"`, `"xpu"`).
/// `"neuron"`, `"rocm"`, `"tpu"`, `"xpu"`).
#[staticmethod]
#[pyo3(name = "from_str")]
fn py_from_str(s: &str) -> PyResult<Self> {
Expand All @@ -144,6 +148,7 @@ impl PyBackend {
PyBackend::Metal => "Metal",
PyBackend::Neuron => "Neuron",
PyBackend::Rocm => "ROCm",
PyBackend::Tpu => "TPU",
PyBackend::Xpu => "XPU",
};
format!("Backend.{variant}")
Expand Down
5 changes: 4 additions & 1 deletion kernels-data/bindings/python/tests/test_kernels_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def test_backend_hash():

def test_backend_unknown():
with pytest.raises(ValueError):
Backend.from_str("tpu")
Backend.from_str("dsp")


def test_backend_all_variants_and_casing():
Expand All @@ -80,8 +80,11 @@ def test_backend_all_variants_and_casing():
assert repr(Backend.ROCm) == "Backend.ROCm"
assert repr(Backend.XPU) == "Backend.XPU"
assert repr(Backend.CANN) == "Backend.CANN"
assert str(Backend.TPU) == "tpu"
assert repr(Backend.TPU) == "Backend.TPU"
assert Backend.from_str("cann") == Backend.CANN
assert Backend.from_str("ROCM") == Backend.ROCm
assert Backend.from_str("TPU") == Backend.TPU
assert Backend.from_str("metal") == Backend.Metal


Expand Down
64 changes: 63 additions & 1 deletion kernels-data/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ pub struct General {

pub cuda: Option<CudaGeneral>,
pub neuron: Option<NeuronGeneral>,
pub tpu: Option<TpuGeneral>,
pub xpu: Option<XpuGeneral>,
}

Expand Down Expand Up @@ -144,6 +145,10 @@ impl General {
.cuda
.as_ref()
.and_then(|cuda| cuda.python_depends.as_ref()),
Backend::Tpu => self
.tpu
.as_ref()
.and_then(|tpu| tpu.python_depends.as_ref()),
Backend::Xpu => self
.xpu
.as_ref()
Expand Down Expand Up @@ -191,6 +196,10 @@ pub struct NeuronGeneral {
pub python_depends: Option<Vec<String>>,
}

pub struct TpuGeneral {
pub python_depends: Option<Vec<String>>,
}

pub struct Hub {
pub repo_id: Option<String>,
pub branch: Option<String>,
Expand Down Expand Up @@ -379,18 +388,20 @@ pub enum Backend {
Metal,
Neuron,
Rocm,
Tpu,
Xpu,
}

impl Backend {
pub const fn all() -> [Backend; 7] {
pub const fn all() -> [Backend; 8] {
[
Backend::Cann,
Backend::Cpu,
Backend::Cuda,
Backend::Metal,
Backend::Neuron,
Backend::Rocm,
Backend::Tpu,
Backend::Xpu,
]
}
Expand All @@ -403,6 +414,7 @@ impl Backend {
Backend::Metal => "metal",
Backend::Neuron => "neuron",
Backend::Rocm => "rocm",
Backend::Tpu => "tpu",
Backend::Xpu => "xpu",
}
}
Expand All @@ -417,6 +429,7 @@ impl Display for Backend {
Backend::Metal => write!(f, "metal"),
Backend::Neuron => write!(f, "neuron"),
Backend::Rocm => write!(f, "rocm"),
Backend::Tpu => write!(f, "tpu"),
Backend::Xpu => write!(f, "xpu"),
}
}
Expand All @@ -433,6 +446,7 @@ impl FromStr for Backend {
"metal" => Ok(Backend::Metal),
"neuron" => Ok(Backend::Neuron),
"rocm" => Ok(Backend::Rocm),
"tpu" => Ok(Backend::Tpu),
"xpu" => Ok(Backend::Xpu),
_ => Err(format!("Unknown backend: {s}")),
}
Expand All @@ -444,3 +458,51 @@ pub enum ConfigError {
#[error("Cannot migrate configuration: {reason:?}")]
Migration { reason: String },
}

#[cfg(test)]
mod tests {
use super::*;

fn general_with_tpu_deps() -> General {
General {
name: KernelName::new("test-kernel").unwrap(),
version: 1,
license: "apache-2.0".to_string(),
upstream: None,
source: None,
backends: vec![Backend::Tpu],
hub: None,
python_depends: None,
cuda: None,
neuron: None,
tpu: Some(TpuGeneral {
python_depends: Some(vec!["torch_tpu".to_string()]),
}),
xpu: None,
}
}

#[test]
fn backend_python_depends_resolves_tpu() {
let general = general_with_tpu_deps();
let deps = general
.backend_python_depends(Backend::Tpu)
.map(|dep| dep.map(|(name, _)| name.to_string()))
.collect::<Result<Vec<_>>>()
.unwrap();

assert_eq!(deps, vec!["torch_tpu".to_string()]);
}

#[test]
fn backend_python_depends_empty_for_backend_without_deps() {
let general = general_with_tpu_deps();

assert!(
general
.backend_python_depends(Backend::Cpu)
.next()
.is_none()
);
}
}
1 change: 1 addition & 0 deletions kernels-data/src/config/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ impl General {
hub: general.hub.map(Into::into),
neuron: None,
python_depends: None,
tpu: None,
xpu: None,
}
}
Expand Down
Loading
Loading