Buckets:
| import"../chunks/DsnmJJEf.js";import{i as de,h as pe,C as he,H as l,a as s,E as ue,s as me}from"../chunks/CKEMnrQO.js";import{p as ye,o as be,s as e,f as ge,a as le,b as Te,c as se,d as te,n as oe,r as ae}from"../chunks/Bb-LL0eD.js";const ke='{"title":"Write kernels","local":"write-kernels","sections":[{"title":"Introduction","local":"introduction","sections":[],"depth":2},{"title":"Setting up environment","local":"setting-up-environment","sections":[{"title":"Quick install","local":"quick-install","sections":[],"depth":3},{"title":"Cloud environment","local":"cloud-environment","sections":[],"depth":3}],"depth":2},{"title":"Starting a new kernel","local":"starting-a-new-kernel","sections":[],"depth":2},{"title":"Kernel project layout","local":"kernel-project-layout","sections":[],"depth":2},{"title":"build.toml","local":"buildtoml","sections":[{"title":"general","local":"general","sections":[],"depth":3},{"title":"general.hub","local":"generalhub","sections":[],"depth":3},{"title":"general.cuda","local":"generalcuda","sections":[],"depth":3},{"title":"Framework sections","local":"framework-sections","sections":[],"depth":3},{"title":"torch","local":"torch","sections":[],"depth":3},{"title":"tvm-ffi","local":"tvm-ffi","sections":[],"depth":3},{"title":"torch-noarch","local":"torch-noarch","sections":[],"depth":3},{"title":"kernel.<name>","local":"kernelltnamegt","sections":[{"title":"cuda","local":"cuda","sections":[],"depth":4},{"title":"rocm","local":"rocm","sections":[],"depth":4},{"title":"xpu","local":"xpu","sections":[],"depth":4}],"depth":3},{"title":"cpu","local":"cpu","sections":[],"depth":3}],"depth":2},{"title":"Torch bindings","local":"torch-bindings","sections":[{"title":"Defining bindings","local":"defining-bindings","sections":[],"depth":3}],"depth":2},{"title":"Using kernel functions from Python","local":"using-kernel-functions-from-python","sections":[],"depth":2},{"title":"Registering Torch operators","local":"registering-torch-operators","sections":[],"depth":2},{"title":"Kernel tests","local":"kernel-tests","sections":[{"title":"Use get_kernel in tests","local":"use-getkernel-in-tests","sections":[],"depth":3},{"title":"Mark CI tests","local":"mark-ci-tests","sections":[],"depth":3}],"depth":2},{"title":"Kernel docs","local":"kernel-docs","sections":[],"depth":2}],"depth":1}';var fe=te('<meta name="hf:doc:metadata"/>'),we=te(`<p></p> <!> <!> <blockquote class="tip"><p>Refer to the <a href="../kernel-requirements">kernel requirements’ page</a> to | |
| get an idea of what is expected from the kernel structure and content.</p></blockquote> <!> <p>The Kernel Hub allows Python libraries and applications to load compute | |
| kernels directly from the <a href="https://hf.co/" rel="nofollow">Hub</a>. To support this kind | |
| of dynamic loading, Hub kernels differ from traditional Python kernel | |
| packages in that they are made to be:</p> <ul><li>Portable: a kernel can be loaded from paths outside <code>PYTHONPATH</code>.</li> <li>Unique: multiple versions of the same kernel can be loaded in the | |
| same Python process.</li> <li>Compatible: kernels must support all recent versions of Python and | |
| the different PyTorch build configurations (various CUDA versions | |
| and C++ ABIs). Furthermore, older C library versions must be supported.</li></ul> <p><code>kernel-builder</code> is a set of tools that can build conforming kernels. It | |
| takes care of:</p> <ul><li>Building kernels for all supported PyTorch configurations (C++98/11 and | |
| different CUDA versions).</li> <li>Compatibility with old glibc and libstdc++ versions, so that kernels also | |
| work on older Linux distributions.</li> <li>Registering Torch ops, such that multiple versions the same kernel can be | |
| loaded without namespace conflicts.</li></ul> <p><code>kernel-builder</code> builds are configured through a <code>build.toml</code> file. <code>build.toml</code> is a simple format that does not require intricate knowledge | |
| of CMake or setuptools.</p> <p>This page describes the directory layout of a kernel-builder project, the | |
| format of the <code>build.toml</code> file, and some additional Python glue that <code>kernel-builder</code> provides. We will use a <a href="https://github.com/huggingface/kernels/tree/main/examples/kernels/relu" rel="nofollow">simple ReLU kernel</a> as the running example. After reading this page, you may also want to have | |
| a look at the more realistic <a href="https://github.com/huggingface/kernels/tree/main/examples/kernels/relu-backprop-compile" rel="nofollow">ReLU kernel with backprop and <code>torch.compile</code></a> support.</p> <blockquote class="tip"><p>We maintain a set of conforming kernels in the <a href="https://github.com/huggingface/kernels-community" rel="nofollow">kernels-community repository</a>. | |
| We try to keep these kernels synced with upstream as much as possible.</p></blockquote> <!> <!> <p>The fastest way to get started is to run the install script. This | |
| installs <a href="https://docs.determinate.systems/determinate-nix/" rel="nofollow">Determinate Nix</a> and <code>kernel-builder</code> in a single command:</p> <!> <p>This will:</p> <ol><li>Install Determinate Nix (if not already installed).</li> <li>Configure the Hugging Face binary cache (to avoid building dependencies from | |
| source).</li> <li>Install <code>kernel-builder</code> via <code>nix profile install</code>.</li></ol> <p>To update <code>kernel-builder</code> later:</p> <!> <p>For a step-by-step breakdown of what the script does, see <a href="nix">Using the kernel builder with Nix</a>.</p> <!> <p>In the <a href="https://github.com/huggingface/kernels/tree/main/terraform" rel="nofollow"><code>terraform</code></a> directory, we provide an | |
| example of programatically spinning up an EC2 instance that is ready | |
| with everything needed for you to start developing and building | |
| kernels.</p> <p>If you use a different provider, the Terraform bridges should be | |
| similar and straightforward to modify.</p> <!> <p>The easiest way to start a new kernel is by using the <code>init</code> subcommand | |
| of <code>kernel-builder</code>. This creates a minimal, compilable kernel:</p> <!> <p>This creates a kernel named <code>mykernel</code> in the directory <code>mykernel</code>. The | |
| kernel is configured to upload to the <code>myorg/mykernel</code> Hub | |
| repository when an upload command is used.</p> <p>By default, the <code>init</code> subcommand creates a CUDA kernel. You can specify | |
| another backend with the <code>--backends</code> option:</p> <!> <p>You can also make a multi-backend kernel by adding all the backends | |
| that you would like to support as arguments to <code>--backends</code>:</p> <!> <p>Finally, if you want to create a kernel for all supported backends, you | |
| can use <code>--backends all</code>.</p> <!> <p>Kernel projects follow this general directory layout:</p> <!> <p>In this example we can find:</p> <ul><li>The build configuration in <code>build.toml</code>.</li> <li>One or more top-level directories containing kernels (<code>mykernel_cuda</code>).</li> <li>The <code>torch-ext</code> directory, which contains: <ul><li><code>torch_binding.h</code>: contains declarations for kernel entry points | |
| (from <code>kernel_a</code> and <code>kernel_b</code>).</li> <li><code>torch_binding.cpp</code>: registers the entry points as Torch ops.</li> <li><code>torch_ext/mykernel</code>: contains any Python wrapping the kernel needs. At the | |
| bare minimum, it should contain an <code>__init__.py</code> file.</li></ul></li> <li>Kernel tests in the directory <code>tests</code>.</li> <li>Benchmarks in the directory <code>benchmarks</code>.</li> <li>A kernel card template in <code>CARD.md</code>. This placeholders in the card are filled | |
| during the kernel build.</li> <li>The Nix flake configuration in <code>flake.nix</code>.</li> <li>An example script that uses the kernel in <code>example.py</code>.</li></ul> <!> <p><code>build.toml</code> tells <code>kernel-builder</code> what to build and how. It looks as | |
| follows for the <code>mykernel</code> kernel:</p> <!> <p>The following sections enumerate all supported options for <code>build.toml</code>.</p> <!> <ul><li><code>name</code> (required): the name of the kernel. The Python code for a Torch | |
| extension must be stored in <code>torch-ext/<name></code>.</li> <li><code>version</code> (int): the major version of the kernel. | |
| The version is written to the kernel’s <code>metadata.json</code> and is used | |
| by the <code>kernel-builder upload</code> command to upload the kernel to a version | |
| branch named <code>v<version></code>.</li> <li><code>edition</code> (required): the <code>build.toml</code> format edition. The current | |
| edition is <code>5</code>. Older <code>build.toml</code> files can be migrated with <code>kernel-builder update-build</code>.</li> <li><code>backends</code> (required): a list of supported backends. Must be one or | |
| more of <code>cpu</code>, <code>cuda</code>, <code>metal</code>, <code>rocm</code>, or <code>xpu</code>.</li> <li><code>upstream</code>: Git-compatible URL (passable to <code>git clone</code>) of the original | |
| upstream repository where the kernel source code comes from.</li> <li><code>source</code>: Git-compatible URL (passable to <code>git clone</code>) of the kernel-builder | |
| formatted source repository. This repository must contain a <code>build.toml</code> and <code>flake.nix</code> so that it can be pulled and built with the kernel builder.</li> <li><code>python-depends</code> (<strong>experimental</strong>): a list of additional Python dependencies | |
| that the kernel requires. The only supported dependencies are <code>einops</code>, <code>helion</code>, and <code>nvidia-cutlass-dsl</code>.</li></ul> <!> <ul><li><code>repo-id</code>: the Hub repository to upload the kernel to when the <code>upload</code> or <code>build-and-upload</code> subcommands of <code>kernel-builder</code> are used.</li></ul> <!> <ul><li><code>maxver</code>: the maximum CUDA toolkit version (inclusive). This option <em>must not</em> be set under normal circumstances, since it can exclude Torch | |
| build variants that are <a href="../kernel-requirements">required for compliant kernels</a>. | |
| This option is provided for kernels that cause compiler errors on | |
| newer CUDA toolkit versions.</li> <li><code>minver</code>: the minimum required CUDA toolkit version. This option <em>must not</em> be set under normal circumstances, since it can exclude Torch | |
| build variants that are <a href="../kernel-requirements">required for compliant kernels</a>. | |
| This option is provided for kernels that require functionality only | |
| provided by newer CUDA toolkits.</li></ul> <!> <p>The framework section specifies framework-specific settings. The name of | |
| the section depends on the framework that is used. The currently supported | |
| frameworks are:</p> <ul><li>AOT-compiled Torch kernel (<code>torch</code>).</li> <li>AOT-compiled TVM-FFI kernel (<code>tvm-ffi</code>).</li> <li>JIT-compiled or not-compiled Torch kernel (<code>torch-noarch</code>, experimental).</li></ul> <!> <p>This framework section is used for AOT-compiled Torch kernels, and has the | |
| following options:</p> <ul><li><p><code>src</code> (required): a list of source files and headers.</p></li> <li><p><code>pyext</code> (optional): the list of extensions for Python files. Default: <code>["py", "pyi"]</code>. Additional extensions can be listed to ship data files | |
| with the kernel, such as <code>json</code> for <a href="triton-autotune">Triton autotune configurations</a>.</p></li> <li><p><code>include</code> (optional): include directories relative to the project root. | |
| Default: <code>[]</code>.</p></li> <li><p><code>maxver</code> (optional): only build for this Torch version and earlier. Use cautiously, since this option produces | |
| non-compliant kernels if the version range does not correspond to the <a href="build-variants">required variants</a>.</p></li> <li><p><code>minver</code> (optional): only build for this Torch version and later. Use cautiously, since this option produces | |
| non-compliant kernels if the version range does not correspond to the <a href="build-variants">required variants</a>.</p></li> <li><p><code>stable-abi</code> (<strong>experimental</strong>): a table mapping backend names to the Torch | |
| version (e.g. <code>"2.11"</code>) that the backend is built against using the Torch | |
| stable ABI. This requires that the kernel itself only use <a href="https://docs.pytorch.org/docs/2.12/notes/libtorch_stable_abi.html" rel="nofollow">stable ABI headers</a>. | |
| For an example, see the <a href="https://github.com/huggingface/kernels/tree/main/examples/kernels/relu-torch-stable-abi" rel="nofollow"><code>relu-torch-stable-abi</code></a> example kernel.</p> <p>Backends that are not listed in the table are built normally (without the | |
| stable ABI), allowing a kernel to mix stable-ABI and full-ABI backends:</p> <!> <p>Entries for backends that are not in <code>[general].backends</code> are ignored, so a | |
| backend can be commented out of <code>[general].backends</code> for testing without | |
| having to also remove it from the table.</p></li></ul> <!> <p>This framework section is used for AOT-compiled TVM-FFI kernels.</p> <ul><li><code>src</code> (required): a list of source files and headers.</li> <li><code>pyext</code> (optional): the list of extensions for Python files. Default: <code>["py", "pyi"]</code>.</li> <li><code>include</code> (optional): include directories relative to the project root. | |
| Default: <code>[]</code>.</li></ul> <!> <p>The <code>torch-noarch</code> section is used for JIT-compiled kernels or kernels that | |
| do not require any ahead-of-time compilation (e.g. a kernel that packages plain PyTorch | |
| layers).</p> <p>Normally, it is expected that this type of kernel runs on all CUDA capabilities | |
| or ROCm architectures. However, for kernels that support only a limited range | |
| of archs, the <code>cuda-capabilites</code> and <code>rocm-archs</code> options can be used to specify | |
| the supported archs. These are then exported to <code>metadata.json</code> for consumption | |
| by e.g. the Hugging Face Hub.</p> <ul><li><code>pyext</code> (optional): the list of extensions for Python files. Default: <code>["py", "pyi"]</code>. Additional extensions can be listed to ship data files | |
| with the kernel, such as <code>json</code> for <a href="triton-autotune">Triton autotune configurations</a>.</li> <li><code>cuda-capabilities</code> (optional): a list of CUDA compute capabilities the | |
| kernel supports (e.g. <code>["9.0", "10.0"]</code>).</li> <li><code>rocm-archs</code> (optional): a list of ROCm architectures the kernel supports | |
| (e.g. <code>["gfx942"]</code>).</li></ul> <!> <p>Specification of a kernel with the name <code><name></code>. Multiple <code>kernel.<name></code> sections can be defined in the same <code>build.toml</code>. | |
| See for example <a href="https://huggingface.co/kernels-community/quantization/" rel="nofollow"><code>kernels-community/quantization</code></a> for an example with multiple kernel sections.</p> <p>The following options can be set for a kernel:</p> <ul><li><code>backend</code> (required): the compute backend of the kernel. The currently | |
| supported backends are <code>cpu</code>, <code>cuda</code>, <code>metal</code>, <code>rocm</code>, and <code>xpu</code>. <strong>The <code>cpu</code> backend is currently experimental and might still change.</strong></li> <li><code>depends</code> (required): a list of dependencies. The supported dependencies | |
| are listed in <a href="https://github.com/huggingface/kernels/blob/main/builder/lib/deps.nix" rel="nofollow"><code>deps.nix</code></a>.</li> <li><code>src</code> (required): a list of source files and headers.</li> <li><code>include</code> (optional): include directories relative to the project root. | |
| Default: <code>[]</code>.</li></ul> <p>Besides these shared options, the following backend-specific options | |
| are available:</p> <!> <ul><li><code>cuda-capabilities</code> (optional): a list of CUDA capabilities that the | |
| kernel should be compiled for. When absent, the kernel will be built | |
| using all capabilities that the builder supports. The effective | |
| capabilities are the intersection of this list and the capabilities | |
| supported by the CUDA compiler. It is recommended to leave this option | |
| unspecified <strong>unless</strong> a kernel requires specific capabilities.</li> <li><code>cuda-flags</code> (optional): additional flags to be passed to <code>nvcc</code>. <strong>Warning</strong>: this option should only be used in exceptional circumstances. | |
| Custom compile flags can interfere with the build process or break | |
| compatibility requirements.</li></ul> <!> <ul><li><code>rocm-archs</code>: a list of ROCm architectures that the kernel should be | |
| compiled for.</li></ul> <!> <ul><li><code>sycl-flags</code>: a list of additional flags to be passed to the SYCL | |
| compiler.</li></ul> <!> <ul><li><code>cxx-flags</code>: a list of additional flags to be passed to the C++ | |
| compiler.</li></ul> <!> <!> <p>Torch bindings are defined in C++, kernels commonly use two files:</p> <ul><li><code>torch_binding.h</code> containing function declarations.</li> <li><code>torch_binding.cpp</code> registering the functions as Torch ops.</li></ul> <p>For instance, the <code>mykernel</code> kernel discussed above has the following | |
| declaration in <code>torch_binding.h</code>:</p> <!> <p>This function is then registered as a Torch op in <code>torch_binding.cpp</code>:</p> <!> <p>This snippet uses macros from <code>registration.h</code> to register the function. <code>registration.h</code> is generated by <code>kernel-builder</code> itself. A function | |
| is registered through the <code>def</code>/<code>ops</code> methods. <code>ops</code> specifies the | |
| function signature following the <a href="https://github.com/pytorch/pytorch/blob/main/aten/src/ATen/native/README.md#func" rel="nofollow">function schema</a>. <code>impl</code> associates the function name with the C/C++ function and | |
| the applicable device.</p> <!> <p>The bindings are typically wrapped in Python code in <code>torch_ext/<name></code>. | |
| The native code is exposed under the <code>torch.ops</code> namespace. However, | |
| we add some unique material to the name of the extension to ensure that | |
| different versions of the same extension can be loaded at the same time. | |
| As a result, the extension is registered as <code>torch.ops.<name>_<unique_material></code>.</p> <p>To deal with this uniqueness, <code>kernel_builder</code> generates a Python module | |
| named <code>_ops</code> that contains an alias for the name. This can be used to | |
| refer to the correct <code>torch.ops</code> module. For example:</p> <!> <!> <p>You may want to register Torch ops from your kernel’s Python code or <a href="https://docs.pytorch.org/tutorials/advanced/custom_ops_landing_page.html" rel="nofollow">register</a> fake ops for <code>torch.compile</code> support. It is important to register | |
| such ops in the namespace that kernel-builder makes for your kernel | |
| build. This is required for compliant kernels to ensure that multiple | |
| versions of the same kernel can be loaded at the same time without | |
| namespace conflicts.</p> <p>You can use the <code>add_op_namespace_prefix</code> to prefix an op name with the | |
| correct prefix. So for instance, replace</p> <!> <p>by</p> <!> <p>As mentioned in the above, the <code>_ops</code> module is generated by kernel-builder.</p> <p>kernel-builder uses a hook to reject incorrect usage of Torch op registration | |
| functions. However, it can only catch direct use of certain <code>torch.library</code> decorators. For instance, the hook would not reject the following decorator, | |
| so it should be seen as a last-resort check if human review failed:</p> <!> <blockquote class="warning"><p>To facilitate static analysis of ops by kernel-builder, <code>add_op_namespace_prefix</code> should not be rewrapped. Furthermore, no fallbacks should be added when importing <code>add_op_namnespace_prefix</code>, since such fallbacks can mask issues (e.g. incorrect import paths), resulting in non-unique op names. Below is an example of this antipattern:</p></blockquote> <!> <!> <!> <p>Kernel tests are stored in the <code>tests</code> directory. Tests must not use direct | |
| imports, but instead use <code>get_kernel</code> to test the kernel as it will be used. | |
| For example:</p> <!> <p>Development shells (<code>kernel-builder devshell</code>/<code>kernel-builder testshell</code>) | |
| will set the <code>LOCAL_KERNELS</code> variable to ensure that the kernel will be | |
| loaded from the development environment.</p> <!> <p>Since running all kernel tests in CI may be prohibitively expensive, the <code>pyproject.toml</code> generated by the builder adds support for the special <code>kernels_ci</code> PyTest marker that can be used as follows:</p> <!> <p>We recommend that you to pick tests that together would catch most error | |
| cases while running within 60 seconds.</p> <p>You can run the tests (e.g. in CI) using:</p> <!> <p>If the kernel supports multiple backends, it will run the test for the | |
| first supported backend that was found, obeying the following order: CUDA, | |
| ROCm, XPU, Metal, CPU. If you would like to the tests for a specific build | |
| variant, you can use <code>nix run .#ciTests.<variant></code>. For instance:</p> <!> <p>When running the tests on a non-NixOS systems, make sure that <a href="https://danieldk.eu/Software/Nix/Nix-CUDA-on-non-NixOS-systems#solutions" rel="nofollow">the CUDA driver library can be found</a>.</p> <!> <p>We provide a utility to generate a system card for a given kernel, utilizing | |
| information from its <code>build.toml</code> and metadata. This system card provides a | |
| reasonable starting point and is meant to be edited afterward by the kernel | |
| developer.</p> <p>The template card is generated as a part of <code>kernel-builder init</code> command and is serialized in the root directory of the kernel.</p> <p>The card will be filled automatically by the builder when using the <code>build-and-upload</code> or <code>build-and-copy</code> command. It will be serialized | |
| to the <code>build</code> sub-directory inside the main kernel directory. It | |
| will be uploaded as <code>README.md</code> to the Hub.</p> <!> <p></p>`,1);function je(ne,ie){ye(ie,!1),be(()=>{new URLSearchParams(window.location.search).get("fw")}),de();var a=we();pe("brj1rc",$=>{var ee=fe();me(ee,"content",ke),le($,ee)});var t=e(ge(a),2);he(t,{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"});var n=e(t,2);l(n,{title:"Write kernels",local:"write-kernels",headingTag:"h1"});var i=e(n,4);l(i,{title:"Introduction",local:"introduction",headingTag:"h2"});var r=e(i,16);l(r,{title:"Setting up environment",local:"setting-up-environment",headingTag:"h2"});var c=e(r,2);l(c,{title:"Quick install",local:"quick-install",headingTag:"h3"});var d=e(c,4);s(d,{code:"Y3VybCUyMC1mc1NMJTIwaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGaHVnZ2luZ2ZhY2UlMkZrZXJuZWxzJTJGbWFpbiUyRmluc3RhbGwuc2glMjAlN0MlMjBiYXNo",highlighted:"curl -fsSL https://raw.githubusercontent.com/huggingface/kernels/main/install.sh | bash",lang:"bash",wrap:!1});var p=e(d,8);s(p,{code:"bml4JTIwcHJvZmlsZSUyMHVwZ3JhZGUlMjAtLWFsbA==",highlighted:"nix profile upgrade --all",lang:"bash",wrap:!1});var h=e(p,4);l(h,{title:"Cloud environment",local:"cloud-environment",headingTag:"h3"});var u=e(h,6);l(u,{title:"Starting a new kernel",local:"starting-a-new-kernel",headingTag:"h2"});var m=e(u,4);s(m,{code:"JTI0JTIwa2VybmVsLWJ1aWxkZXIlMjBpbml0JTIwLS1uYW1lJTIwbXlvcmclMkZteWtlcm5lbCUwQUluaXRpYWxpemVkJTIwJTYwbXlvcmclMkZteWtlcm5lbCU2MCUyMGF0JTIwJTJGaG9tZSUyRmRhbmllbCUyRmdpdCUyRmtlcm5lbHMlMkZleGFtcGxlcyUyRmtlcm5lbHMlMkZteWtlcm5lbA==",highlighted:"$ kernel-builder init --name myorg/mykernel\nInitialized `myorg/mykernel` at /home/daniel/git/kernels/examples/kernels/mykernel",lang:"bash",wrap:!1});var y=e(m,6);s(y,{code:"JTI0JTIwa2VybmVsLWJ1aWxkZXIlMjBpbml0JTIwLS1uYW1lJTIwbXlvcmclMkZteWtlcm5lbCUyMC0tYmFja2VuZHMlMjB4cHU=",highlighted:"$ kernel-builder init --name myorg/mykernel --backends xpu",lang:"bash",wrap:!1});var b=e(y,4);s(b,{code:"JTI0JTIwa2VybmVsLWJ1aWxkZXIlMjBpbml0JTIwLS1uYW1lJTIwbXlvcmclMkZteWtlcm5lbCUyMC0tYmFja2VuZHMlMjBjdWRhJTIweHB1JTBBSW5pdGlhbGl6ZWQlMjAlNjBteW9yZyUyRm15a2VybmVsJTYwJTIwYXQlMjAlMkZob21lJTJGZGFuaWVsJTJGZ2l0JTJGa2VybmVscyUyRmV4YW1wbGVzJTJGa2VybmVscyUyRm15a2VybmVs",highlighted:"$ kernel-builder init --name myorg/mykernel --backends cuda xpu\nInitialized `myorg/mykernel` at /home/daniel/git/kernels/examples/kernels/mykernel",lang:"bash",wrap:!1});var g=e(b,4);l(g,{title:"Kernel project layout",local:"kernel-project-layout",headingTag:"h2"});var T=e(g,4);s(T,{code:"bXlrZXJuZWwlMEElRTIlOTQlOUMlRTIlOTQlODAlRTIlOTQlODAlMjBiZW5jaG1hcmtzJTBBJUUyJTk0JTgyJTIwJTIwJTIwJUUyJTk0JTk0JUUyJTk0JTgwJUUyJTk0JTgwJTIwYmVuY2htYXJrLnB5JTBBJUUyJTk0JTlDJUUyJTk0JTgwJUUyJTk0JTgwJTIwYnVpbGQudG9tbCUwQSVFMiU5NCU5QyVFMiU5NCU4MCVFMiU5NCU4MCUyMENBUkQubWQlMEElRTIlOTQlOUMlRTIlOTQlODAlRTIlOTQlODAlMjBleGFtcGxlLnB5JTBBJUUyJTk0JTlDJUUyJTk0JTgwJUUyJTk0JTgwJTIwZmxha2Uubml4JTBBJUUyJTk0JTlDJUUyJTk0JTgwJUUyJTk0JTgwJTIwbXlrZXJuZWxfY3VkYSUwQSVFMiU5NCU4MiUyMCUyMCUyMCVFMiU5NCU5NCVFMiU5NCU4MCVFMiU5NCU4MCUyMG15a2VybmVsLmN1JTBBJUUyJTk0JTlDJUUyJTk0JTgwJUUyJTk0JTgwJTIwdGVzdHMlMEElRTIlOTQlODIlMjAlMjAlMjAlRTIlOTQlOUMlRTIlOTQlODAlRTIlOTQlODAlMjBfX2luaXRfXy5weSUwQSVFMiU5NCU4MiUyMCUyMCUyMCVFMiU5NCU5NCVFMiU5NCU4MCVFMiU5NCU4MCUyMHRlc3RfbXlrZXJuZWwucHklMEElRTIlOTQlOTQlRTIlOTQlODAlRTIlOTQlODAlMjB0b3JjaC1leHQlMEElRTIlOTQlOUMlRTIlOTQlODAlRTIlOTQlODAlMjBteWtlcm5lbCUwQSVFMiU5NCU4MiUyMCUyMCUyMCVFMiU5NCU5NCVFMiU5NCU4MCVFMiU5NCU4MCUyMF9faW5pdF9fLnB5JTBBJUUyJTk0JTlDJUUyJTk0JTgwJUUyJTk0JTgwJTIwdG9yY2hfYmluZGluZy5jcHAlMEElRTIlOTQlOTQlRTIlOTQlODAlRTIlOTQlODAlMjB0b3JjaF9iaW5kaW5nLmg=",highlighted:`mykernel | |
| ├── benchmarks | |
| │ └── benchmark.py | |
| ├── build.toml | |
| ├── CARD.md | |
| ├── example.py | |
| ├── flake.nix | |
| ├── mykernel_cuda | |
| │ └── mykernel.cu | |
| ├── tests | |
| │ ├── __init__.py | |
| │ └── test_mykernel.py | |
| └── torch-ext | |
| ├── mykernel | |
| │ └── __init__.py | |
| ├── torch_binding.cpp | |
| └── torch_binding.h`,lang:"text",wrap:!1});var k=e(T,6);l(k,{title:"build.toml",local:"buildtoml",headingTag:"h2"});var f=e(k,4);s(f,{code:"JTVCZ2VuZXJhbCU1RCUwQWJhY2tlbmRzJTIwJTNEJTIwJTVCJTBBJTIwJTIwJTIyY3VkYSUyMiUyQyUwQSU1RCUwQW5hbWUlMjAlM0QlMjAlMjJteWtlcm5lbCUyMiUwQXZlcnNpb24lMjAlM0QlMjAxJTBBZWRpdGlvbiUyMCUzRCUyMDUlMEElMEElNUJnZW5lcmFsLmh1YiU1RCUwQXJlcG8taWQlMjAlM0QlMjAlMjJteW9yZyUyRm15a2VybmVsJTIyJTBBJTBBJTVCdG9yY2glNUQlMEFzcmMlMjAlM0QlMjAlNUIlMEElMjAlMjAlMjJ0b3JjaC1leHQlMkZ0b3JjaF9iaW5kaW5nLmNwcCUyMiUyQyUwQSUyMCUyMCUyMnRvcmNoLWV4dCUyRnRvcmNoX2JpbmRpbmcuaCUyMiUyQyUwQSU1RCUwQSUwQSU1Qmtlcm5lbC5teWtlcm5lbCU1RCUwQWJhY2tlbmQlMjAlM0QlMjAlMjJjdWRhJTIyJTBBZGVwZW5kcyUyMCUzRCUyMCU1QiUyMnRvcmNoJTIyJTVEJTBBc3JjJTIwJTNEJTIwJTVCJTIybXlrZXJuZWxfY3VkYSUyRm15a2VybmVsLmN1JTIyJTVEJTBBJTIzJTIwSWYlMjB0aGUlMjBrZXJuZWwlMjBpcyUyMG9ubHklMjBzdXBwb3J0ZWQlMjBvbiUyMHNwZWNpZmljJTIwY2FwYWJpbGl0aWVzJTJDJTIwc2V0JTIwdGhlJTBBJTIzJTIwY3VkYS1jYXBhYmlsaXRpZXMlMjBvcHRpb24lM0ElMEElMjMlMEElMjMlMjBjdWRhLWNhcGFiaWxpdGllcyUyMCUzRCUyMCU1QiUyMCUyMjkuMCUyMiUyQyUyMCUyMjEwLjAlMjIlMkMlMjAlMjIxMi4wJTIyJTIwJTVE",highlighted:`<span class="hljs-section">[general]</span> | |
| <span class="hljs-attr">backends</span> = [ | |
| <span class="hljs-string">"cuda"</span>, | |
| ] | |
| <span class="hljs-attr">name</span> = <span class="hljs-string">"mykernel"</span> | |
| <span class="hljs-attr">version</span> = <span class="hljs-number">1</span> | |
| <span class="hljs-attr">edition</span> = <span class="hljs-number">5</span> | |
| <span class="hljs-section">[general.hub]</span> | |
| <span class="hljs-attr">repo-id</span> = <span class="hljs-string">"myorg/mykernel"</span> | |
| <span class="hljs-section">[torch]</span> | |
| <span class="hljs-attr">src</span> = [ | |
| <span class="hljs-string">"torch-ext/torch_binding.cpp"</span>, | |
| <span class="hljs-string">"torch-ext/torch_binding.h"</span>, | |
| ] | |
| <span class="hljs-section">[kernel.mykernel]</span> | |
| <span class="hljs-attr">backend</span> = <span class="hljs-string">"cuda"</span> | |
| <span class="hljs-attr">depends</span> = [<span class="hljs-string">"torch"</span>] | |
| <span class="hljs-attr">src</span> = [<span class="hljs-string">"mykernel_cuda/mykernel.cu"</span>] | |
| <span class="hljs-comment"># If the kernel is only supported on specific capabilities, set the</span> | |
| <span class="hljs-comment"># cuda-capabilities option:</span> | |
| <span class="hljs-comment">#</span> | |
| <span class="hljs-comment"># cuda-capabilities = [ "9.0", "10.0", "12.0" ]</span>`,lang:"toml",wrap:!1});var w=e(f,4);l(w,{title:"general",local:"general",headingTag:"h3"});var J=e(w,4);l(J,{title:"general.hub",local:"generalhub",headingTag:"h3"});var M=e(J,4);l(M,{title:"general.cuda",local:"generalcuda",headingTag:"h3"});var U=e(M,4);l(U,{title:"Framework sections",local:"framework-sections",headingTag:"h3"});var j=e(U,6);l(j,{title:"torch",local:"torch",headingTag:"h3"});var o=e(j,4),I=e(se(o),10),re=e(se(I),4);s(re,{code:"JTVCdG9yY2guc3RhYmxlLWFiaSU1RCUwQWN1ZGElMjAlM0QlMjAlMjIyLjExJTIyJTBBcm9jbSUyMCUzRCUyMCUyMjIuOSUyMg==",highlighted:`<span class="hljs-section">[torch.stable-abi]</span> | |
| <span class="hljs-attr">cuda</span> = <span class="hljs-string">"2.11"</span> | |
| <span class="hljs-attr">rocm</span> = <span class="hljs-string">"2.9"</span>`,lang:"toml",wrap:!1}),oe(2),ae(I),ae(o);var C=e(o,2);l(C,{title:"tvm-ffi",local:"tvm-ffi",headingTag:"h3"});var v=e(C,6);l(v,{title:"torch-noarch",local:"torch-noarch",headingTag:"h3"});var _=e(v,8);l(_,{title:"kernel.<name>",local:"kernelltnamegt",headingTag:"h3"});var Z=e(_,10);l(Z,{title:"cuda",local:"cuda",headingTag:"h4"});var B=e(Z,4);l(B,{title:"rocm",local:"rocm",headingTag:"h4"});var V=e(B,4);l(V,{title:"xpu",local:"xpu",headingTag:"h4"});var R=e(V,4);l(R,{title:"cpu",local:"cpu",headingTag:"h3"});var W=e(R,4);l(W,{title:"Torch bindings",local:"torch-bindings",headingTag:"h2"});var x=e(W,2);l(x,{title:"Defining bindings",local:"defining-bindings",headingTag:"h3"});var N=e(x,8);s(N,{code:"JTIzcHJhZ21hJTIwb25jZSUwQSUwQSUyM2luY2x1ZGUlMjAlM0N0b3JjaCUyRnRvcmNoLmglM0UlMEElMEF2b2lkJTIwbXlrZXJuZWwodG9yY2glM0ElM0FUZW5zb3IlMjAlMjZvdXQlMkMlMjB0b3JjaCUzQSUzQVRlbnNvciUyMGNvbnN0JTIwJTI2aW5wdXQpJTNC",highlighted:`<span class="hljs-meta">#<span class="hljs-keyword">pragma</span> once</span> | |
| <span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><torch/torch.h></span></span> | |
| <span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">mykernel</span><span class="hljs-params">(torch::Tensor &out, torch::Tensor <span class="hljs-type">const</span> &input)</span></span>;`,lang:"cpp",wrap:!1});var Q=e(N,4);s(Q,{code:"JTIzaW5jbHVkZSUyMCUzQ3RvcmNoJTJGbGlicmFyeS5oJTNFJTBBJTBBJTIzaW5jbHVkZSUyMCUyMnJlZ2lzdHJhdGlvbi5oJTIyJTBBJTIzaW5jbHVkZSUyMCUyMnRvcmNoX2JpbmRpbmcuaCUyMiUwQSUwQVRPUkNIX0xJQlJBUllfRVhQQU5EKFRPUkNIX0VYVEVOU0lPTl9OQU1FJTJDJTIwb3BzKSUyMCU3QiUwQSUyMCUyMG9wcy5kZWYoJTIybXlrZXJuZWwoVGVuc29yISUyMG91dCUyQyUyMFRlbnNvciUyMGlucHV0KSUyMC0lM0UlMjAoKSUyMiklM0IlMEElMjNpZiUyMGRlZmluZWQoQ1VEQV9LRVJORUwpJTIwJTdDJTdDJTIwZGVmaW5lZChST0NNX0tFUk5FTCklMEElMjAlMjBvcHMuaW1wbCglMjJteWtlcm5lbCUyMiUyQyUyMHRvcmNoJTNBJTNBa0NVREElMkMlMjAlMjZteWtlcm5lbCklM0IlMEElMjNlbmRpZiUwQSU3RCUwQSUwQVJFR0lTVEVSX0VYVEVOU0lPTihUT1JDSF9FWFRFTlNJT05fTkFNRSk=",highlighted:`<span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><torch/library.h></span></span> | |
| <span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"registration.h"</span></span> | |
| <span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"torch_binding.h"</span></span> | |
| <span class="hljs-built_in">TORCH_LIBRARY_EXPAND</span>(TORCH_EXTENSION_NAME, ops) { | |
| ops.<span class="hljs-built_in">def</span>(<span class="hljs-string">"mykernel(Tensor! out, Tensor input) -> ()"</span>); | |
| <span class="hljs-meta">#<span class="hljs-keyword">if</span> defined(CUDA_KERNEL) || defined(ROCM_KERNEL)</span> | |
| ops.<span class="hljs-built_in">impl</span>(<span class="hljs-string">"mykernel"</span>, torch::kCUDA, &mykernel); | |
| <span class="hljs-meta">#<span class="hljs-keyword">endif</span></span> | |
| } | |
| <span class="hljs-built_in">REGISTER_EXTENSION</span>(TORCH_EXTENSION_NAME)`,lang:"cpp",wrap:!1});var E=e(Q,4);l(E,{title:"Using kernel functions from Python",local:"using-kernel-functions-from-python",headingTag:"h2"});var A=e(E,6);s(A,{code:"ZnJvbSUyMHR5cGluZyUyMGltcG9ydCUyME9wdGlvbmFsJTBBJTBBaW1wb3J0JTIwdG9yY2glMEElMEFmcm9tJTIwLl9vcHMlMjBpbXBvcnQlMjBvcHMlMEElMEElMEFkZWYlMjBteWtlcm5lbCh4JTNBJTIwdG9yY2guVGVuc29yJTJDJTIwb3V0JTNBJTIwT3B0aW9uYWwlNUJ0b3JjaC5UZW5zb3IlNUQlMjAlM0QlMjBOb25lKSUyMC0lM0UlMjB0b3JjaC5UZW5zb3IlM0ElMEElMjAlMjAlMjAlMjBpZiUyMG91dCUyMGlzJTIwTm9uZSUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMG91dCUyMCUzRCUyMHRvcmNoLmVtcHR5X2xpa2UoeCklMEElMjAlMjAlMjAlMjBvcHMubXlrZXJuZWwob3V0JTJDJTIweCklMEElMjAlMjAlMjAlMjByZXR1cm4lMjBvdXQ=",highlighted:`<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">Optional</span> | |
| <span class="hljs-keyword">import</span> torch | |
| <span class="hljs-keyword">from</span> ._ops <span class="hljs-keyword">import</span> ops | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">mykernel</span>(<span class="hljs-params">x: torch.Tensor, out: <span class="hljs-type">Optional</span>[torch.Tensor] = <span class="hljs-literal">None</span></span>) -> torch.Tensor: | |
| <span class="hljs-keyword">if</span> out <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>: | |
| out = torch.empty_like(x) | |
| ops.mykernel(out, x) | |
| <span class="hljs-keyword">return</span> out`,lang:"python",wrap:!1});var X=e(A,2);l(X,{title:"Registering Torch operators",local:"registering-torch-operators",headingTag:"h2"});var S=e(X,6);s(S,{code:"JTQwdG9yY2gubGlicmFyeS5yZWdpc3Rlcl9mYWtlKCUyMnJlbHUlM0ElM0FyZWx1X2Z3ZCUyMiklMEFkZWYlMjByZWx1X2Z3ZF9mYWtlKGlucHV0JTNBJTIwdG9yY2guVGVuc29yKSUyMC0lM0UlMjB0b3JjaC5UZW5zb3IlM0ElMEElMjAlMjAlMjAlMjByZXR1cm4lMjB0b3JjaC5lbXB0eV9saWtlKGlucHV0KQ==",highlighted:`<span class="hljs-meta">@torch.library.register_fake(<span class="hljs-params"><span class="hljs-string">"relu::relu_fwd"</span></span>)</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">relu_fwd_fake</span>(<span class="hljs-params"><span class="hljs-built_in">input</span>: torch.Tensor</span>) -> torch.Tensor: | |
| <span class="hljs-keyword">return</span> torch.empty_like(<span class="hljs-built_in">input</span>)`,lang:"python",wrap:!1});var F=e(S,4);s(F,{code:"ZnJvbSUyMC5fb3BzJTIwaW1wb3J0JTIwYWRkX29wX25hbWVzcGFjZV9wcmVmaXglMEElMEElNDB0b3JjaC5saWJyYXJ5LnJlZ2lzdGVyX2Zha2UoYWRkX29wX25hbWVzcGFjZV9wcmVmaXgoJTIycmVsdV9md2QlMjIpKSUwQWRlZiUyMHJlbHVfZndkX2Zha2UoaW5wdXQlM0ElMjB0b3JjaC5UZW5zb3IpJTIwLSUzRSUyMHRvcmNoLlRlbnNvciUzQSUwQSUyMCUyMCUyMCUyMHJldHVybiUyMHRvcmNoLmVtcHR5X2xpa2UoaW5wdXQp",highlighted:`<span class="hljs-keyword">from</span> ._ops <span class="hljs-keyword">import</span> add_op_namespace_prefix | |
| <span class="hljs-meta">@torch.library.register_fake(<span class="hljs-params">add_op_namespace_prefix(<span class="hljs-params"><span class="hljs-string">"relu_fwd"</span></span>)</span>)</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">relu_fwd_fake</span>(<span class="hljs-params"><span class="hljs-built_in">input</span>: torch.Tensor</span>) -> torch.Tensor: | |
| <span class="hljs-keyword">return</span> torch.empty_like(<span class="hljs-built_in">input</span>)`,lang:"python",wrap:!1});var G=e(F,6);s(G,{code:"JTQwc29tZV9pbmRpcmVjdGlvbl9mb3JfcmVnaXN0ZXJfZmFrZSglMjJyZWx1JTNBJTNBcmVsdV9md2QlMjIpJTBBZGVmJTIwcmVsdV9md2RfZmFrZShpbnB1dCUzQSUyMHRvcmNoLlRlbnNvciklMjAtJTNFJTIwdG9yY2guVGVuc29yJTNBJTBBJTIwJTIwJTIwJTIwcmV0dXJuJTIwdG9yY2guZW1wdHlfbGlrZShpbnB1dCk=",highlighted:`<span class="hljs-meta">@some_indirection_for_register_fake(<span class="hljs-params"><span class="hljs-string">"relu::relu_fwd"</span></span>)</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">relu_fwd_fake</span>(<span class="hljs-params"><span class="hljs-built_in">input</span>: torch.Tensor</span>) -> torch.Tensor: | |
| <span class="hljs-keyword">return</span> torch.empty_like(<span class="hljs-built_in">input</span>)`,lang:"python",wrap:!1});var Y=e(G,4);s(Y,{code:"dHJ5JTNBJTBBJTIwJTIwJTIwJTIwZnJvbSUyMC5fb3BzJTIwaW1wb3J0JTIwYWRkX29wX25hbWVzcGFjZV9wcmVmaXglMjBhcyUyMF9nZW5lcmF0ZWRfYWRkX29wX25hbWVzcGFjZV9wcmVmaXglMEFleGNlcHQlMjBJbXBvcnRFcnJvciUzQSUwQSUyMCUyMCUyMCUyMGRlZiUyMF9nZW5lcmF0ZWRfYWRkX29wX25hbWVzcGFjZV9wcmVmaXgobmFtZSUzQSUyMHN0ciklMjAtJTNFJTIwc3RyJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmV0dXJuJTIwbmFtZSUyMGlmJTIwJTIyJTNBJTNBJTIyJTIwaW4lMjBuYW1lJTIwZWxzZSUyMGYlMjJteV9rZXJuZWwlM0ElM0ElN0JuYW1lJTdEJTIyJTBBJTBBZGVmJTIwYWRkX29wX25hbWVzcGFjZV9wcmVmaXgobmFtZSUzQSUyMHN0ciklMjAtJTNFJTIwc3RyJTNBJTBBJTIwJTIwJTIwJTIwcmV0dXJuJTIwX2dlbmVyYXRlZF9hZGRfb3BfbmFtZXNwYWNlX3ByZWZpeChuYW1lKQ==",highlighted:`<span class="hljs-keyword">try</span>: | |
| <span class="hljs-keyword">from</span> ._ops <span class="hljs-keyword">import</span> add_op_namespace_prefix <span class="hljs-keyword">as</span> _generated_add_op_namespace_prefix | |
| <span class="hljs-keyword">except</span> ImportError: | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">_generated_add_op_namespace_prefix</span>(<span class="hljs-params">name: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">str</span>: | |
| <span class="hljs-keyword">return</span> name <span class="hljs-keyword">if</span> <span class="hljs-string">"::"</span> <span class="hljs-keyword">in</span> name <span class="hljs-keyword">else</span> <span class="hljs-string">f"my_kernel::<span class="hljs-subst">{name}</span>"</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">add_op_namespace_prefix</span>(<span class="hljs-params">name: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">str</span>: | |
| <span class="hljs-keyword">return</span> _generated_add_op_namespace_prefix(name)`,lang:"py",wrap:!1});var q=e(Y,2);l(q,{title:"Kernel tests",local:"kernel-tests",headingTag:"h2"});var H=e(q,2);l(H,{title:"Use get_kernel in tests",local:"use-getkernel-in-tests",headingTag:"h3"});var O=e(H,4);s(O,{code:"aW1wb3J0JTIwa2VybmVscyUwQWltcG9ydCUyMHRvcmNoJTBBaW1wb3J0JTIwdG9yY2gubm4uZnVuY3Rpb25hbCUyMGFzJTIwRiUwQSUwQXJlbHUlMjAlM0QlMjBrZXJuZWxzLmdldF9rZXJuZWwoJTIya2VybmVscy1jb21tdW5pdHklMkZyZWx1JTIyJTJDJTIwdmVyc2lvbiUzRDEpJTBBJTBBZGVmJTIwdGVzdF9yZWx1KCklM0ElMEElMjAlMjAlMjAlMjB4JTIwJTNEJTIwdG9yY2gucmFuZG4oMTAyNCUyQyUyMDEwMjQlMkMlMjBkdHlwZSUzRHRvcmNoLmZsb2F0MzIlMkMlMjBkZXZpY2UlM0R0b3JjaC5kZXZpY2UoJTIyY3VkYSUyMikpJTBBJTIwJTIwJTIwJTIweSUyMCUzRCUyMHJlbHUucmVsdSh4JTJDJTIwdG9yY2guZW1wdHlfbGlrZSh4KSklMEElMjAlMjAlMjAlMjB5X3JlZiUyMCUzRCUyMEYucmVsdSh4KSUwQSUyMCUyMCUyMCUyMHRvcmNoLnRlc3RpbmcuYXNzZXJ0X2Nsb3NlKHlfcmVmJTJDJTIweSk=",highlighted:`<span class="hljs-keyword">import</span> kernels | |
| <span class="hljs-keyword">import</span> torch | |
| <span class="hljs-keyword">import</span> torch.nn.functional <span class="hljs-keyword">as</span> F | |
| relu = kernels.get_kernel(<span class="hljs-string">"kernels-community/relu"</span>, version=<span class="hljs-number">1</span>) | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">test_relu</span>(): | |
| x = torch.randn(<span class="hljs-number">1024</span>, <span class="hljs-number">1024</span>, dtype=torch.float32, device=torch.device(<span class="hljs-string">"cuda"</span>)) | |
| y = relu.relu(x, torch.empty_like(x)) | |
| y_ref = F.relu(x) | |
| torch.testing.assert_close(y_ref, y)`,lang:"python",wrap:!1});var z=e(O,4);l(z,{title:"Mark CI tests",local:"mark-ci-tests",headingTag:"h3"});var D=e(z,4);s(D,{code:"aW1wb3J0JTIwcHl0ZXN0JTBBJTBBJTQwcHl0ZXN0Lm1hcmsua2VybmVsc19jaSUwQWRlZiUyMHRlc3RfbXlrZXJuZWwoKSUzQSUwQSUyMCUyMC4uLg==",highlighted:`<span class="hljs-keyword">import</span> pytest | |
| <span class="hljs-meta">@pytest.mark.kernels_ci</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">test_mykernel</span>(): | |
| ...`,lang:"python",wrap:!1});var L=e(D,6);s(L,{code:"JTI0JTIwbml4JTIwcnVuJTIwLiUyM2NpLXRlc3Q=",highlighted:"$ nix run .#ci-test",lang:"bash",wrap:!1});var P=e(L,4);s(P,{code:"JTI0JTIwbml4JTIwcnVuJTIwLiUyM2NpVGVzdHMudG9yY2gyMTAtY3h4MTEtY3B1LXg4Nl82NC1saW51eA==",highlighted:"$ nix run .#ciTests.torch210-cxx11-cpu-x86_64-linux",lang:"bash",wrap:!1});var K=e(P,4);l(K,{title:"Kernel docs",local:"kernel-docs",headingTag:"h2"});var ce=e(K,8);ue(ce,{source:"https://github.com/huggingface/kernels/blob/main/docs/source/builder/writing-kernels.md"}),oe(2),le(ne,a),Te()}export{je as component}; | |
Xet Storage Details
- Size:
- 41 kB
- Xet hash:
- c0271a0030510c9ee0a2735577fffb7c68040fb2f1224e4ebda75a4363e1d57d
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.