hsfzxjy/npunlock

Write and run custom C kernels for Intel Core Ultra NPUs

C

40

58 commits

updated Sep 23, 2026

See the code

See what people are saying

SourceMessageScoreDate

Show HN: Npunlock – Run custom C kernels for Intel NPUs

I have no access to other environment setting, so, sadly, that's the best I can do for now. But based on my understanding, playing this on Linux or newer NPU generations might be possible. I have recorded my hypotheses in [0]. Verifying the hypotheses would require additional utility tools, which I…

0

Sep 23, 2026

README

npunlock

Intel ships programmable SHAVE cores inside its NPUs, but the public stack exposes only graph-level programming. npunlock reconstructs the missing path from custom C code to a runnable NPU kernel.

How npunlock adds custom C kernels to an Intel NPU graph

The current implementation has been verified on Windows x64 with Meteor Lake / NPU3720.

Latest breakthrough — 2026-09-23: One native graph can execute independent FP32-unary and FP16-binary custom branches; explicit ACT-group preflight handles the compiler's branch reordering. Evidence and limits.

Quick example

This complete FP32 GELU example embeds the C kernel in Python, places it in an NPU graph, and checks the result against NumPy. The bundled npunlock/npu3720_kernel.h target header supplies the NPU3720 invocation and tensor-address helpers. The tested MoviTools toolchain makes most conventional libm functions available to kernels without including <math.h>; this example calls tanhf directly. See the mlibm.a symbol inventory for the observed candidates.

import numpy as np
import npunlock as npu

npu.configure(movi_dll_dir=r"C:\path\to\MVC_DEPEND")

gelu_c: bytes = b"""
#define MLIBM_DEFINE_LINK_COMPAT 1
#include <npunlock/npu3720_kernel.h>

void controlled_act(unsigned layerParams) {
    act_abi_invocation invocation;
    ACT_ABI_LOAD_INVOCATION32_OR_RETURN(layerParams, invocation);
    const float *in = ACT_ABI_INPUT_PTR32(const float, invocation, 0u);
    float *out = ACT_ABI_OUTPUT_PTR32(float, invocation, 1u);
    const float SQRT_2_DIV_PI = 0.7978845608028654f;
    for (unsigned i = 0; i < invocation.element_count; ++i) {
        float x = in[i];
        float w = x + 0.044715f * x * x * x;
        w = tanhf(w * SQRT_2_DIV_PI);
        out[i] = 0.5f * x * (1.0f + w);
    }
}
"""

N = 2048
x = npu.input("x", shape=(1, N), dtype="f32")
y = npu.custom(
    x,
    source=gelu_c,
    carrier="Abs",
    _name="y",
)

program = npu.compile(npu.Graph(inputs=[x], outputs=[y], name="gelu_f32_example"))

input_value = np.linspace(-4, 4, N, dtype=np.float32).reshape(1, -1)
output = program.run({"x": input_value})["y"]
reference = 0.5 * input_value * (
    1.0
    + np.tanh(
        np.sqrt(2.0 / np.pi)
        * (input_value + 0.044715 * input_value**3)
    )
)
print(f"maximum absolute error: {np.max(np.abs(output - reference)):g}")

The same code is available as the runnable FP32 GELU example. See also the FP16 GELU and multi-layer two-input examples, plus a mixed-precision graph with unary and binary custom branches.

Why npunlock?

Intel's normal NPU software accepts graphs made from operations its compiler supports; it does not expose a public workflow for supplying a C implementation for an operation. The NPU's ACT-SHAVE processors are programmable and run software kernels. npunlock makes those processors usable for compatible custom graph operations while retaining Intel's compiler and driver for the surrounding graph and hardware execution.

Requirements

  • Windows x64
  • Meteor Lake / Intel NPU3720
  • an installed Intel NPU driver for the device
  • Python 3.10 or newer
  • CMake 3.24 or newer and an installed MSVC toolchain for source installation
  • the extracted MoviTools MVC_DEPEND toolchain for custom C compilation

OpenVINO is not required as a runtime, Python package, or compiler frontend. npunlock does emit OpenVINO-format IR for the installed Intel driver.

Install

npunlock is currently installed from a source checkout:

python -m pip install .

The build bundles npunlock.dll and npunlock_worker.exe inside the Python package, so normal Python use does not require a separate native path.

Get MoviTools

Custom C compilation uses Intel/Movidius MoviTools, which npunlock does not redistribute or download.

A MoviTools package verified to work was found in a legacy Lenovo driver pack. See Getting MoviTools for the official download, hash, extraction command, and expected layout.

Extract the MVC_DEPEND payload from Lenovo's older Intel NPU driver package 31.0.100.1688, but remember, DO NOT install or downgrade to that driver. All we need is the bundled MoviTools.

Run an example

Point npunlock at the extracted MVC_DEPEND root and run GELU:

$env:NPUNLOCK_MOVITOOLS_DIR = 'C:\path\to\MVC_DEPEND'
python examples\example_gelu.py

The example runs on the NPU and reports its maximum error against a NumPy reference.

What currently works

  • compile user-written C into ACT-SHAVE machine code
  • run custom kernels inside Intel NPU graphs
  • static dense FP16 unary and two-input custom kernels
  • a verified unary FP32 path
  • one graph containing independent FP32-unary and FP16-binary custom branches
  • nonlinear math such as GELU and tanhf
  • reusable NumPy-compatible host/NPU shared input and output buffers
  • Python, CLI, and native C APIs

Current limitations

Support is experimental and currently limited to Windows x64, Meteor Lake / NPU3720, static shapes, compatible ACT carriers, and known tensor layouts. Connected mixed-precision conversion groups are not yet patch-discoverable; the verified mixed-precision example uses independent branches. Other NPU generations have not been verified. See Current limitations for the full compatibility boundary.

Help test Linux and newer NPUs

Have an NPU3720 Linux system or a newer Intel NPU? Contributions are welcome. Two routes look especially promising but remain untested:

  • a patched NPU3720 graph produced on Windows may run on Linux because the NPU firmware executes the custom machine code; building SHAVE code on Linux would additionally require a way to load the Windows MoviTools DLLs;
  • newer NPUs may execute the existing 3720xx SHAVE image, or an older OEM driver package for that generation may provide matching MoviTools components.

Both need hardware validation, driver/firmware version records, and output comparison against a host oracle. If you can test either path, feedback, failure reports, and code contributions are welcome. See Porting to Linux and newer NPUs for the hypotheses, caveats, and a suggested test plan.

Documentation

[!WARNING] A note on AI use: I did use AI while building this project--for scaffolding, repetitive implementation work, converting my reverse-engineered results into organized documentation, and fixing my English. The reverse engineering, experiments, debugging, and technical conclusions came from hands-on work. If that doesn’t bother you, there’s a pretty deep and surprisingly satisfying rabbit hole ahead.

License

npunlock is licensed under the Apache License 2.0. MoviTools and the Intel/Movidius libraries are external proprietary dependencies and are not covered or redistributed by this repository.

intel
npu
npu-acceleration
openvino

Contributors

hsfzxjy

58 commits

hsfzxjy/npunlock

Write and run custom C kernels for Intel Core Ultra NPUs

C

40

58 commits

updated Sep 23, 2026

See the code

See what people are saying

SourceMessageScoreDate

Show HN: Npunlock – Run custom C kernels for Intel NPUs

I have no access to other environment setting, so, sadly, that's the best I can do for now. But based on my understanding, playing this on Linux or newer NPU generations might be possible. I have recorded my hypotheses in [0]. Verifying the hypotheses would require additional utility tools, which I…

0

Sep 23, 2026

README

npunlock

Intel ships programmable SHAVE cores inside its NPUs, but the public stack exposes only graph-level programming. npunlock reconstructs the missing path from custom C code to a runnable NPU kernel.

How npunlock adds custom C kernels to an Intel NPU graph

The current implementation has been verified on Windows x64 with Meteor Lake / NPU3720.

Latest breakthrough — 2026-09-23: One native graph can execute independent FP32-unary and FP16-binary custom branches; explicit ACT-group preflight handles the compiler's branch reordering. Evidence and limits.

Quick example

This complete FP32 GELU example embeds the C kernel in Python, places it in an NPU graph, and checks the result against NumPy. The bundled npunlock/npu3720_kernel.h target header supplies the NPU3720 invocation and tensor-address helpers. The tested MoviTools toolchain makes most conventional libm functions available to kernels without including <math.h>; this example calls tanhf directly. See the mlibm.a symbol inventory for the observed candidates.

import numpy as np
import npunlock as npu

npu.configure(movi_dll_dir=r"C:\path\to\MVC_DEPEND")

gelu_c: bytes = b"""
#define MLIBM_DEFINE_LINK_COMPAT 1
#include <npunlock/npu3720_kernel.h>

void controlled_act(unsigned layerParams) {
    act_abi_invocation invocation;
    ACT_ABI_LOAD_INVOCATION32_OR_RETURN(layerParams, invocation);
    const float *in = ACT_ABI_INPUT_PTR32(const float, invocation, 0u);
    float *out = ACT_ABI_OUTPUT_PTR32(float, invocation, 1u);
    const float SQRT_2_DIV_PI = 0.7978845608028654f;
    for (unsigned i = 0; i < invocation.element_count; ++i) {
        float x = in[i];
        float w = x + 0.044715f * x * x * x;
        w = tanhf(w * SQRT_2_DIV_PI);
        out[i] = 0.5f * x * (1.0f + w);
    }
}
"""

N = 2048
x = npu.input("x", shape=(1, N), dtype="f32")
y = npu.custom(
    x,
    source=gelu_c,
    carrier="Abs",
    _name="y",
)

program = npu.compile(npu.Graph(inputs=[x], outputs=[y], name="gelu_f32_example"))

input_value = np.linspace(-4, 4, N, dtype=np.float32).reshape(1, -1)
output = program.run({"x": input_value})["y"]
reference = 0.5 * input_value * (
    1.0
    + np.tanh(
        np.sqrt(2.0 / np.pi)
        * (input_value + 0.044715 * input_value**3)
    )
)
print(f"maximum absolute error: {np.max(np.abs(output - reference)):g}")

The same code is available as the runnable FP32 GELU example. See also the FP16 GELU and multi-layer two-input examples, plus a mixed-precision graph with unary and binary custom branches.

Why npunlock?

Intel's normal NPU software accepts graphs made from operations its compiler supports; it does not expose a public workflow for supplying a C implementation for an operation. The NPU's ACT-SHAVE processors are programmable and run software kernels. npunlock makes those processors usable for compatible custom graph operations while retaining Intel's compiler and driver for the surrounding graph and hardware execution.

Requirements

  • Windows x64
  • Meteor Lake / Intel NPU3720
  • an installed Intel NPU driver for the device
  • Python 3.10 or newer
  • CMake 3.24 or newer and an installed MSVC toolchain for source installation
  • the extracted MoviTools MVC_DEPEND toolchain for custom C compilation

OpenVINO is not required as a runtime, Python package, or compiler frontend. npunlock does emit OpenVINO-format IR for the installed Intel driver.

Install

npunlock is currently installed from a source checkout:

python -m pip install .

The build bundles npunlock.dll and npunlock_worker.exe inside the Python package, so normal Python use does not require a separate native path.

Get MoviTools

Custom C compilation uses Intel/Movidius MoviTools, which npunlock does not redistribute or download.

A MoviTools package verified to work was found in a legacy Lenovo driver pack. See Getting MoviTools for the official download, hash, extraction command, and expected layout.

Extract the MVC_DEPEND payload from Lenovo's older Intel NPU driver package 31.0.100.1688, but remember, DO NOT install or downgrade to that driver. All we need is the bundled MoviTools.

Run an example

Point npunlock at the extracted MVC_DEPEND root and run GELU:

$env:NPUNLOCK_MOVITOOLS_DIR = 'C:\path\to\MVC_DEPEND'
python examples\example_gelu.py

The example runs on the NPU and reports its maximum error against a NumPy reference.

What currently works

  • compile user-written C into ACT-SHAVE machine code
  • run custom kernels inside Intel NPU graphs
  • static dense FP16 unary and two-input custom kernels
  • a verified unary FP32 path
  • one graph containing independent FP32-unary and FP16-binary custom branches
  • nonlinear math such as GELU and tanhf
  • reusable NumPy-compatible host/NPU shared input and output buffers
  • Python, CLI, and native C APIs

Current limitations

Support is experimental and currently limited to Windows x64, Meteor Lake / NPU3720, static shapes, compatible ACT carriers, and known tensor layouts. Connected mixed-precision conversion groups are not yet patch-discoverable; the verified mixed-precision example uses independent branches. Other NPU generations have not been verified. See Current limitations for the full compatibility boundary.

Help test Linux and newer NPUs

Have an NPU3720 Linux system or a newer Intel NPU? Contributions are welcome. Two routes look especially promising but remain untested:

  • a patched NPU3720 graph produced on Windows may run on Linux because the NPU firmware executes the custom machine code; building SHAVE code on Linux would additionally require a way to load the Windows MoviTools DLLs;
  • newer NPUs may execute the existing 3720xx SHAVE image, or an older OEM driver package for that generation may provide matching MoviTools components.

Both need hardware validation, driver/firmware version records, and output comparison against a host oracle. If you can test either path, feedback, failure reports, and code contributions are welcome. See Porting to Linux and newer NPUs for the hypotheses, caveats, and a suggested test plan.

Documentation

[!WARNING] A note on AI use: I did use AI while building this project--for scaffolding, repetitive implementation work, converting my reverse-engineered results into organized documentation, and fixing my English. The reverse engineering, experiments, debugging, and technical conclusions came from hands-on work. If that doesn’t bother you, there’s a pretty deep and surprisingly satisfying rabbit hole ahead.

License

npunlock is licensed under the Apache License 2.0. MoviTools and the Intel/Movidius libraries are external proprietary dependencies and are not covered or redistributed by this repository.

intel
npu
npu-acceleration
openvino

Contributors

hsfzxjy

58 commits

Languages

C

76.8%

Python

20.0%

CMake

2.8%