Intel Triton XPU #6053 — Can deepcopy() and != Prove JIT Global-State Compatibility?
Static source analysis, Part 2 — How far can an object snapshot and an equality check go in validating compiled state?
A JIT compiler does not compile a function from source alone.
Global constants and other values referenced by the function may also influence the generated kernel.
Consider a Triton kernel that depends on a global configuration value:
BLOCK_SIZE = 128If the kernel is compiled while BLOCK_SIZE is 128, the generated code may embed assumptions based on that value.
Now suppose the global is changed to 256 after compilation.
If Triton silently reuses the old kernel, the Python program and the compiled code may no longer agree about the state under which the kernel was created.
Intel’s Triton repository uses DependenciesFinder to detect this kind of change.
Its central question is:
Is the global state used during compilation still compatible with the kernel being launched now?
The current implementation attempts to answer that question with two Python mechanisms:
copy.deepcopy()
+
!=How Triton records global values
DependenciesFinder walks the Python AST of a JIT function and identifies names and attributes referenced by that function.
Modules, Triton builtins, some callable objects, and other values that are not intended to be tracked are handled separately or excluded.
For a tracked global, the implementation stores a snapshot in a structure shaped like this:
self.used_global_vals[
(name, id(var_dict))
] = (
copy.deepcopy(val),
var_dict,
)The key contains both:
the global variable name
the identity of the corresponding globals dictionary
That distinction matters because two functions from different modules may use the same global name while referring to different values.
The stored value is not the original object.
It is a deep copy of the object as it existed when dependency analysis ran.
The snapshot is compared immediately before launch
Before launching a compiled kernel, Triton checks the current global values against the stored snapshots.
The core logic is effectively:
for (name, _), (val, globals_dict) in self.used_global_vals.items():
if (new_val := globals_dict.get(name, not_present)) != val:
raise RuntimeError(
f"Global variable {name} has changed "
f"since we compiled this kernel"
)The overall flow is:
Global value observed during dependency analysis
↓
Snapshot stored with deepcopy()
↓
Current value read before launch
↓
Current value != stored snapshot
↓
Launch rejected if they differA similar equality check is used when global dependencies from nested JIT functions are merged.
The intention is reasonable.
Silently launching a kernel whose compilation assumptions no longer match the Python state would be risky.
Failing closed is safer than quietly reusing stale code.
The question is whether Python object equality expresses the compatibility property that a JIT compiler actually needs.
Why use deepcopy() instead of storing the original reference?
Storing only the original object reference would make in-place mutation difficult to detect.
Consider a global dictionary:
CONFIG = {
"num_warps": 4,
}Suppose Triton stores a reference to CONFIG.
Later, the same dictionary object is modified:
CONFIG["num_warps"] = 8The stored reference and the current global still point to the same object.
Both now expose the updated value.
The original state has been lost.
A deep copy preserves an independent snapshot:
Compilation-time CONFIG
→ independent copied object
Current CONFIG
→ original object in its current stateFor values such as integers, strings, tuples, lists, and ordinary dictionaries, this is an intuitive approach.
The snapshot preserves the past.
But not every Python object behaves like an ordinary value container.
Some objects cannot be deep-copied safely
copy.deepcopy() recursively copies the state reachable from an object.
That operation is not valid for every kind of object.
Potentially problematic examples include:
thread locks
open file handles
native library handles
device contexts
streams or queues
wrappers around C or C++ runtime resources
opaque objects implemented by extension modules
A simple Python lock already demonstrates the category:
import copy
import threading
state = threading.Lock()
snapshot = copy.deepcopy(state)If an object of this kind reaches the tracked-global path, dependency analysis can fail before Triton even reaches the compatibility comparison.
However, the scope must be stated carefully.
Issue #6053 originally mentioned backend-related objects such as drivers, streams, and targets.
The current static evidence does not establish that Intel XPU’s actual driver, stream, or target objects necessarily enter used_global_vals.
The stream used by JITFunction.run(), for example, is obtained through the runtime driver path rather than automatically being discovered as a global referenced by the user kernel.
What the code establishes is narrower:
Any object accepted as a tracked global is implicitly expected to support
deepcopy().
What remains unproven is:
A real Intel XPU runtime object currently reaches this path and fails during copying.
A successful copy can still produce an immediate false positive
Even when deepcopy() succeeds, equality may not behave as expected.
Consider a class that does not define a value-based __eq__() method:
class IdentityState:
pass
current = IdentityState()
snapshot = copy.deepcopy(current)
print(current == snapshot)The original object and the copy may contain equivalent internal state.
But they are still two different objects.
With default object equality semantics, the result can be False.
Under Triton’s comparison:
current != snapshotthe value may appear to have changed even though no mutation occurred.
The sequence becomes:
Original object during analysis
→ deepcopy creates a second object
Current global before launch
→ still points to the untouched original
Equality based on identity
→ objects compare as differentThat is a false positive.
The kernel state may still be compatible, yet Triton could reject the launch.
This example demonstrates a general possibility.
It is not, by itself, evidence that an Intel XPU kernel currently fails in this way.
The reverse is possible: equal objects may still be incompatible
A false negative is also possible.
An object may define equality using only a subset of its state:
class BackendState:
def __init__(self, version, device_id, native_handle):
self.version = version
self.device_id = device_id
self.native_handle = native_handle
def __eq__(self, other):
return self.version == other.versionTwo instances with the same version compare as equal.
But they may differ in:
device identity
native handle
driver generation
compiler configuration
supported hardware features
memory model
runtime context
The result can be:
Python equality
→ equal
Compilation or runtime compatibility
→ potentially differentThe != operator uses whatever equality semantics the object’s author chose.
There is no general guarantee that those semantics were designed to answer:
Can a kernel compiled under one object state be safely launched under the other?
Application-level equality and compiler compatibility are not necessarily the same relation.
Object identity, value equality, and compilation compatibility are different questions
The boundary becomes clearer when the concepts are separated.
Object identity
a is bDo both names refer to the exact same Python object?
Value equality
a == bDo the objects consider themselves equal according to their own equality implementation?
Compilation compatibility
Can a kernel compiled using state a
be safely reused while the runtime is in state b?These questions can produce different answers.
Two distinct objects may be value-equal and fully compatible:
different identity
+
same value
+
same valid compiled resultA single unchanged Python wrapper may also point to an external resource whose state has changed:
same Python object
+
external runtime state changed
+
old compiled kernel no longer compatibledeepcopy() and != primarily operate on Python-visible value state.
The compiler ultimately needs an answer about reusable machine code.
External state may not be visible inside the Python object
A wrapper object can remain unchanged while the resource it represents changes outside Python.
Examples include:
file contents
shared-library versions
driver capabilities
environment variables
device configuration
resources referenced by native handles
state owned by another process or runtime service
Suppose a Python wrapper contains the same fields before and after such a change.
The comparison may report equality:
Python fields
→ unchanged
External environment
→ changed
Equality result
→ equal
Kernel compatibility
→ potentially differentA deep copy captures the object’s Python-visible state.
It does not automatically capture the full environment that gives that object its runtime meaning.
This is why compiler caches often use explicit fingerprints rather than attempting to clone arbitrary runtime objects.
A fingerprint can extract only the state that affects compilation, such as:
backend name
target architecture
driver version
compiler version
feature flags
relevant environment variablesThose values can then be serialized canonically and incorporated into a cache or dependency identity.
A fingerprint is not automatically correct either
Replacing every deep copy with a hash would not solve the problem by itself.
The fingerprint still needs a contract.
If it includes too much state, irrelevant changes cause unnecessary invalidation:
too much state included
→ false miss
→ unnecessary recompilationIf it omits compilation-relevant state, stale kernels can remain valid according to the key:
too little state included
→ false hit
→ incompatible kernel reuseA safer design might involve one or more of the following:
restrict tracked globals to immutable or simple value types
require complex objects to provide an explicit compatibility fingerprint
reject objects whose compatibility semantics cannot be determined
let each backend provide a backend-specific state key
separate “raise an error” from “invalidate and recompile” as distinct policies
define which global changes affect source hashing and which affect only runtime validation
The correct design depends on the kinds of global values Triton intentionally supports.
The code already recognizes that not all values can be tracked uniformly
DependenciesFinder does not blindly deep-copy every referenced value.
It already treats several categories specially.
Examples include:
Nonemodules
Triton builtins
selected libdevice stubs
ordinary callable objects
other
JITCallableinstancesobjects marked with
__triton_aggregate__
A referenced JIT function contributes its cache key rather than being copied as an arbitrary Python object.
A Triton aggregate can expose selected hash_attrs rather than relying on an unrestricted object snapshot.
This shows that the implementation already acknowledges a real constraint:
Not every Python value can be represented through the same dependency mechanism.
But after those special cases are removed, the remaining tracked values still pass through the general policy:
deepcopy()
+
equality comparisonThe precise class of values for which that policy is guaranteed to be meaningful is not clearly expressed as an interface contract.
What changed between the issue date and the current code?
Issue #6053 was opened in February 2026 based on static source analysis.
A source snapshot near the issue date shows the same central behavior:
tracked globals were stored using
copy.deepcopy()overlapping global dependencies from nested JIT functions were compared with
!=globals were checked again before launch using equality
The current main branch retains that core design.
Surrounding implementation details and supported object categories may have evolved.
But the architectural question remains present:
Is a deep-copied Python value and its equality relation sufficient to represent JIT compatibility?
The continued presence of the pattern does not prove an Intel XPU bug.
It confirms only that the question was not made irrelevant by the code having completely removed the mechanism.
What would need to be reproduced?
Moving from static concern to an actual finding requires targeted tests.
A non-copyable tracked global
Global value is accepted by DependenciesFinder
+
deepcopy() cannot copy it
→ dependency analysis or compilation failsThis would establish the practical boundary of copyability.
An identity-based equality object
No state mutation
+
deepcopy creates a second instance
+
original != snapshot
→ false “global changed” errorThis would demonstrate a concrete false positive.
An incomplete equality implementation
Python equality reports equal
+
compilation-relevant internal state differs
→ change remains undetectedThis would demonstrate a possible false negative at the Python-object level.
A real XPU-related configuration value
The strongest test would use an actual value that:
can be referenced by a Triton JIT function,
is tracked by
DependenciesFinder,affects generated XPU code or launch compatibility, and
can change after the first compilation.
The test would then determine:
Does DependenciesFinder track it?
Does the change alter generated code?
Does the equality check detect it?
Does Triton reject, recompile, or reuse the old kernel?This final step is essential.
A generic Python counterexample demonstrates that the policy has limits.
It does not establish that those limits currently create an Intel XPU correctness failure.
What is confirmed
The source supports the following statements:
Code near the issue date stored tracked globals with
copy.deepcopy().The current implementation retains the same core snapshot mechanism.
Current values are compared with stored snapshots using
!=.Global dependencies shared across nested JIT functions are also reconciled using equality.
The generic path does not expose a formal compiler-compatibility fingerprint for arbitrary tracked objects.
Several object categories are already excluded or treated specially.
What is not confirmed
The current evidence does not establish that:
an Intel XPU driver, stream, or target object actually enters this path
a real XPU backend object fails during
deepcopy()current equality behavior creates a false positive in an Intel kernel
a compilation-relevant XPU state change is missed by equality
a stale XPU kernel is reused because of this policy
a numerical error or launch failure has been reproduced
The current conclusion must therefore remain narrower:
There is a conceptual gap between general Python equality and JIT compatibility. A concrete Intel XPU correctness failure has not yet been demonstrated.
A snapshot preserves the past. It does not define compatibility.
deepcopy() is useful.
It can preserve an earlier Python state even when the original object is later mutated in place.
Equality is useful as well.
For integers, strings, tuples, and ordinary value containers, it can detect meaningful changes with little complexity.
The limitation lies in the question those operations answer.
deepcopy()
→ Can this Python-visible state be copied?
!=
→ Does the object’s equality model consider the values different?The JIT compiler needs an answer to a stricter question:
Can the machine code created under the earlier state
still be used safely under the current state?The three questions overlap for simple values.
They are not universally equivalent.
A snapshot preserves what Python could see.
Equality reports what the object author chose to compare.
Compatibility requires an explicit definition of which state changes invalidate the compiled result.
The second concern in Intel Triton XPU Issue #6053 therefore comes down to this:
If an object says it is equal to its previous snapshot, what proves that the compiled kernel should agree?
The source code does not yet provide a universal answer.
Related material
Issue status: Open
Evidence: Historical and current static source analysis
Runtime reproduction: Not yet performed
Current conclusion: The deepcopy() plus equality policy remains present, but an Intel XPU compatibility failure has not been confirmed.
This is Part 2 of a four-part series on Intel Triton XPU Issue #6053.
Part 3 examines how native_specialize_impl() uses pointer alignment to divide calls into separate kernel variants, and whether the shared 16-byte specialization boundary has the same value for Intel XPU.
#Intel #Triton #XPU #JITCompiler #PythonInternals #CodeAnalysis #SoftwareArchitecture