Skip to content

[Func] Allow proper preservations/reference across copy and pickle - #873

Open
vasqu wants to merge 3 commits into
huggingface:mainfrom
vasqu:fix-func-kernels
Open

vasqu wants to merge 3 commits into
huggingface:mainfrom
vasqu:fix-func-kernels

Conversation

@vasqu

@vasqu vasqu commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

As per title, we want copy/deepcopy as well as pickle to keep proper references to the actual functions. This is currently failing / losing track of the correct references. The original issue was noticed by @SunMarc see repro

import copy
import pickle

from torch import nn

from kernels import Mode, kernelize, use_kernel_mapping
from kernels import use_kernel_forward_from_hub, use_kernelized_func


@use_kernel_forward_from_hub("f")
def f(x):
    return x + 1


@use_kernelized_func(f)
class Model(nn.Module):
    def forward(self, x):
        return f(x)


def add_ten(x):
    return x + 10


a, b = Model(), Model()

# 1. Simulate swapping A's function: B changes too.
a._kernel_funcs["f"].forward = add_ten
print(a(1), b(1))  # 11, 11

# 2. Reset a copy: its forward still calls the global wrapper.
c = copy.deepcopy(a)
with use_kernel_mapping({}, inherit_mapping=False):
    kernelize(c, device="cpu", mode=Mode.INFERENCE)

print(c._kernel_funcs["f"](1), c(1), a(1))  # 2, 11, 11

# 3. Pickle doesn't work
d = pickle.loads(pickle.dumps(a))
# AttributeError: Can't pickle local object '_create_func_module.<locals>.Func'

@vasqu

vasqu commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

cc @danieldk

@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@vasqu
vasqu marked this pull request as draft October 2, 2026 18:10
@vasqu

vasqu commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Still draft, noticed we actually dont want singleton but exactly the reverse

@vasqu
vasqu marked this pull request as ready for review October 2, 2026 20:25
Comment on lines +799 to +827
def __setstate__(self, state):
state, forward_func = state
self.__dict__.update(state)

if forward_func is not None:
# Rebind fwd set by `kernelize` to the restored instance
self.forward = MethodType(forward_func, self)

def __reduce__(self):
module = importlib.import_module(func.__module__)

# Global case => just resolve by name
if getattr(module, func.__name__, None) is self:
return func.__name__

# The own private wrapper case => rebuild a separate instance and restore its state
forward_func = None
state = self.__dict__.copy()
if isinstance(forward := state.get("forward"), MethodType):
if forward.__self__ is self:
# Store the function separately and rebind it on restore
forward_func = forward.__func__
del state["forward"]

return (
_rebuild_kernel_func,
(func.__module__, func.__name__),
(state, forward_func),
)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

pickle is the complex case as this is just due to pickle 😅 I think we can keep it since some do use pickle but they should use safetensors

return decorator


class CompileableContextVar:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it's needed for torch compile but i think there are works to make it native within dynamo, still need it for BC either way

self.context_var.reset(token)


_ACTIVE_KERNEL_FUNCS = CompileableContextVar("_ACTIVE_KERNEL_FUNCS")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

also let me know whether to move things to other files as im not super familiar with the repo structure I thought its simpler to just add it directly for now

@sayakpaul
sayakpaul requested a review from danieldk October 5, 2026 05:24

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants