-
Notifications
You must be signed in to change notification settings - Fork 191
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
monitoring vs serialization extremely poor performance with many apps #2848
Comments
As part of trying to quantify a potential fix to this, I wrote a script that monkeypatches
I ran this against current Monitoring on or off? Decoration style: This latter decoration may sound surprising but it's relatively common in power user cases where the callable to be executed is dynamically generated - for example, ctrl_bps_parsl in LSST generates and decorates a The results against master are here. The values in cells are serialized bytes/invocation and serialization time/invocation.
The bottom right corner is a demonstration of this current issue #2848 This test is run on my laptop with a custom-build python 3.11. |
I've prototyped removing this cache entire, in PR #2852. These are the results of the same test:
This makes the decorate-once, reuse-apps, monitoring enabled case more expensive (by around 5 milliseconds per call in this test), the same cost as the decorate many case - because caching is no longer happening It also pulls the decorate many case down to that same value - because bad-cache behaviour is removed. I think this is the right way to go, in light of more recent experiences with serialization which push me towards any caching happening deeping inside the serialization code, rather than futher out towards user space. |
See issue #2848 for a bunch of description and benchmarking.
Describe the bug
PR #2468 moves the monitoring remote wrapper into its own module -
parsl.monitoring.remote
- because serialization of that wrapper was bringing along with it the entirely of the module it was defined in. By placing the remote wrapper in its own module, the size of the module brought along can be reduced.However, subsequently, PR #2493 introduces a cache that is stored as a global in the
parsl.monitoring.remote
module, to try to work around a lack of caching inparsl.serialize
except at the top level - prior to PR #2493, a new callable would be defined for each invocation when used with monitoring, bringing along with it the task and try ID in a closure. PR #2493 instead tries to make a callable that is re-used between multiple invocations of the same app, with the task and try ID added as additional parameters: attempting to be equivalent to a closure but unwrapped in a way that the naive parsl.serialize callable serializer can see that. To do that, it introduces its own cache, so that any particular app will be wrapped only once.Because this cache is in the
parsl.monitoring.remote
module, it is serialized as part of serializing a monitoring-wrapped app invocation.In workflows with a small number of apps, this is a small-ish (but undesired) overhead. In workflows with many apps (in my case, ctrl_parsl_bps which makes a new app for every task), this cache becomes large and the cache easily grows to hundreds of kilobytes, repeatedly serialized on each invocation.
While debugging this, I discovered that this serialization of caching only happens when the monitoring wrapper has the functools.wraps decorator applied -
parsl/parsl/monitoring/remote.py
Line 47 in 4b8b0b8
Removing that wraps decorator makes this problem go away.
More nuanced, having the wraps decorator copy a smaller subset of attributes, rather than its default of functools.WRAPPER_ASSIGNMENTS, also makes the problem go away:
This copies the same attributes except for the
__module__
attribute.It isn't clear to me why copying that attribute onto the wrapped function causes the module to be serialized, when that module is probably also the
__module__
attribute of the underlying function.To Reproduce
Observe the size of serialized messages using a configuration such as
parsl/tests/configs/htex_local_alternate.py
.Expected behavior
This cache should not be transmitted.
This whole caching feature in parsl.monitoring.remote only exists to cope with the lack of nested-function-away caching inside
parsl.serialize.concretes.DillCallableSerializer
and so perhaps some more work can happen there to make nested functions get cached, at which point PR #2493 could be reverted.Environment
my laptop, parsl master 4b8b0b8
The text was updated successfully, but these errors were encountered: