Skip to content

Recompile stale BASE_DIR#415

Open
kennykos wants to merge 11 commits intomainfrom
kennykos/recompile
Open

Recompile stale BASE_DIR#415
kennykos wants to merge 11 commits intomainfrom
kennykos/recompile

Conversation

@kennykos
Copy link
Copy Markdown
Collaborator

Closes #100, #234.

Features

1. AST-hashed compilation directories
pk_cpp output directories now include an AST_<hash> subdirectory that encodes a structural hash of the compiled workunit. On each invocation, PyKokkos computes the current AST hash and compares it against the on-disk directory name; if the AST hashes differ, recompilation is triggered. This replaces the previous approach which did not check if the compiled AST matched the current AST.

2. Incremental recompilation on AST change
When a workunit's AST hash changes, initialize_directory renames the old AST_<hash> directory to the new hash rather than discarding it. Only CMakeCache.txt and cmake.check_cache are deleted (as they contain hardcoded absolute paths that CMake rejects after a rename), while all object files and link artifacts in build/ are preserved. This allows CMake to perform an incremental rebuild rather than compiling from scratch.

3. Recompilation unit test
Adds test_recompilation which verifies end-to-end that modifying a @pk.workunit body triggers a correct recompile. The test writes a buggy kernel (arr[i] += 2), runs it and asserts the output, then overwrites it with the fixed kernel (arr[i] += 1) and asserts the recompiled output, confirming that stale builds are invalidated and that the new kernel produces correct results.

We add a hashing to the AST directly
to check if the workunit needs to be
recompiled.

NOTE: Ideally, we could edit the functor.hpp directly so we do not need
to bring in all of Kokkos again, but this approach works for now.
@kennykos kennykos requested review from JBludau and gliga April 29, 2026 21:31

# get parser signature
signature = ast.dump(self.tree)
self.signature = hashlib.md5(signature.encode()).hexdigest()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how expensive is this? I assume our ast's for kernels are small that this should not be an issue?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I didn't do a performance test. This block is only done when the workunit is first seen by pykokkos, so it is a startup cost that will not add overhead during repeated execution.

In most cases the ast's should be relatively small; e.g., in my Ewald code, the slowest time for this block of code is 0.013 seconds.

Comment thread pykokkos/core/cpp_setup.py Outdated
Comment thread tests/test_recompile.py Outdated
Comment thread tests/test_recompile.py
except AssertionError as e:
raise AssertionError(
f"kernel is incorrect\nactual: {arr_correct}\ndesired: {expected}"
) from e
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this test does not check that values of signature on disk changed or something was renamed

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I kept it abstract in case we want to change in implementation details down the road (i.e., if we want to move away from renaming or change the directory structure).

Copy link
Copy Markdown
Contributor

@gliga gliga left a comment

Choose a reason for hiding this comment

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

Overall, good change. See comments.

@gliga
Copy link
Copy Markdown
Contributor

gliga commented Apr 30, 2026

I do not like the renaming part, but we can keep it and see when/if it breaks.

@gliga
Copy link
Copy Markdown
Contributor

gliga commented Apr 30, 2026

Are we ever going to change the name of that directory? It has been a while that we wanted to move to .pykokkos or we can use .pk

@kennykos kennykos changed the title Recompile stale pk_cpp Recompile stale BASE_DIR Apr 30, 2026
@kennykos
Copy link
Copy Markdown
Collaborator Author

Are we ever going to change the name of that directory? It has been a while that we wanted to move to .pykokkos or we can use .pk

Changed to .pykokkos in #416.

Comment thread pykokkos/core/cpp_setup.py Outdated
Comment on lines +120 to +121
Creates an output directory, overwriting an existing directory with the same name.
Checks if an older AST directory exists, and if so copies over the relevant information.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe we want to reverse the order of the comments?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Changed in ee7e739.

Comment on lines +131 to +136
# make the parent directory if necessary
try:
os.makedirs(name.parent, exist_ok=True)
except FileExistsError:
pass

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why would we want to catch a FileExistsError if we pass exists_ok=true?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Removed in ee7e739, this was a vestigial code pattern.

Comment thread pykokkos/core/cpp_setup.py Outdated
old_dir = [
f for f in name.parent.parent.iterdir() if f.is_dir() and f != name.parent
]
if len(old_dir) == 1:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why a list if we just expect 0 or 1 entries?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I chose list comprehension as it seemed the most pythonic thing to do, added a comment to specify that we have 0 or 1 entries.

Comment on lines +195 to +196
if ast_signature is not None:
out_dir = out_dir / f"AST_{ast_signature}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hmm so we have a hierarchy which has the ast signature as the highest priority ... but is there cases where the ast signature would not trigger but the others would?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, consider the scenario:

  • workunit v0 is compiled with pk.float arrays;
  • an edit is made and we now have ATS has for workunit v1;
  • workunit v1 is compiled with pk.double arrays;
  • workunit v1 is called again with pk.float arrays. In this case, the type hash would trigger, but the ats hash would not as it is out of date.

Comment thread tests/test_recompile.py Outdated
Comment on lines +76 to +80
# assert add2 array is correct
try:
np.testing.assert_equal(arr_buggy, np.zeros(n, dtype=np.int32) + 2)
except AssertionError as e:
raise AssertionError("buggy kernel is incorrect") from e
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

maybe not call it buggy but rather v1 and v2?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Addressed in 19b56c0.

* Change ordering of comments for clarity;
* remove vestigial try/except blocks
@kennykos kennykos requested a review from JBludau April 30, 2026 19:36
@kennykos
Copy link
Copy Markdown
Collaborator Author

@JBludau I want to make sure you're aware of the new commit a810722.

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.

ENH, DOC: recompile on change

3 participants