Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partially load modules from compiler cache, handling possible race condition #440

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from

Conversation

wllgrnt
Copy link

@wllgrnt wllgrnt commented Feb 24, 2023

Motivation and Context

See #414 for motivation behind commits 65b622c, f0747ba, 12e35a8.

These commits introduced an issue where if two processes working in parallel generated the same function in different cache modules, our assumptions about the module -> function mapping would break and the functions would not be properly linked. (Previously this would be dealt with by marking one of the modules invalid). Commit ffd7492 handles this by maintaining a function name and a (realized name / link name / instance name), and using the latter internally.

Approach

Key approach here was ensuring that the concept of a link name did not leak outside the cache - cache users should not need to have any notion of which modules a given function is in.

How Has This Been Tested?

We use a MockDirectory class (written by @guslonergan ) to generate versions of the cache with multiple modules containing the same function, approximating the state of the cache following a race.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.

Augustus Lonergan and others added 3 commits February 24, 2023 16:22
Current implementation of the interface, used via
_loadFromCompilerCache, runs loadForSymbol for a given link name and
then returns two dicts representing everything the cache touched during
this load process. Maintaining this interface makes the partial-load
refactor difficult, and muddies the converter layers/cache relationship.
Here we alter the API so that we can ask the cache for
a TypedCallTarget, and add modules, and that's it. This means getting
rid of _loadFromCompilerCache, and associated registers for tracking
what's being converted. Also means passing the cache down to the
native_ast_to_llvm layer.
Previously we would always attempt to link and validate all global
variables when loading a module from the cache. This caused linking
errors, or validation errors, or deserialization errors, and meant we
needed the mark_invalid mechanism for handling modules with outdated
global variables. Here we add double-serialised global variables, and
only deserialize,link&validate the subset required for the function
required (and its dependencies). This requires the cache to store
a function and global_var dependency graph. Also add utility methods
for GlobalVariableDefinition.
Pickle supports a protocol where __reduce__returns a string giving
the global name. Implementing this behaviour lets us serialize numpy
ufuncs. Also adjust installInflightFunctions to handle new load
behaviour, fix an instability caused by not leaving LoadedModule
objects in memory, and adjust alternative test. Also ensure that the new
pickle protocol support works with 'local names' (e.g. dotted method names).
@wllgrnt wllgrnt force-pushed the will-compiler-cache-partial-load-multi-module branch 4 times, most recently from d77f679 to 12d4b42 Compare March 2, 2023 16:10
William Grant added 2 commits March 2, 2023 14:14
Previous iterations of the cache assumed a one-one-one function name to
module mapping, however it's possible to end up with many modules which
contain the same function (e.g due to a race condition when using multiple
processes, but other scenarios could exist in the future). This commit
separates the func_name (the id for the function) with the link_name
(the unique id for a given function in a given module). This distinction
is not exposed outside the cache - when asked for a target the cache
chooses which version to return (currently just the first one it sees).
During the compilation of one Entrypointed function it's possible to import a module which
calls a second Entrypointed function. This breaks our model of the
compilation process and could cause deadlocks, so instead throw an
ImportError.
@wllgrnt wllgrnt force-pushed the will-compiler-cache-partial-load-multi-module branch from 12d4b42 to e2d754a Compare March 2, 2023 19:19
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.

1 participant