-
Notifications
You must be signed in to change notification settings - Fork 235
api: revamp subsampling factors to avoid duplicates #2575
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
Comments suppressed due to low confidence (2)
tests/test_dimension.py:1900
- [nitpick] Consider renaming 'test_cond_copy' to a more descriptive name (e.g., 'test_operator_parameters_caching') to better convey the intent of the test.
def test_cond_copy(self):
devito/types/dimension.py:826
- [nitpick] Consider adding a docstring to 'SubsamplingFactor' to clearly document its caching functionality and intended usage.
class SubsamplingFactor(Constant, Cached):
4edf17b
to
07c5547
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2575 +/- ##
=======================================
Coverage 91.91% 91.91%
=======================================
Files 245 245
Lines 48313 48362 +49
Branches 4244 4248 +4
=======================================
+ Hits 44406 44454 +48
+ Misses 3232 3231 -1
- Partials 675 677 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks ok to me. Where were the duplicated subsampling factors becoming an issue?
07c5547
to
6828f53
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What makes me think here is that it feels like we're relying on caching for correctness, and that shouldn't the case. Caching should just be a thing for performance. We know it's not always been like that in the past, but we've improved the situation over the years. This however looks like a step back
Also, it doesn't really make much sense that we use a Constant that is an Uncached, being a subclass of DataSymbol, and now here we have a subclass of Constant that is Cached instead, as it's like bending the class hierarchy.
I think the true issue here is that we're using a Constant
, whose underlying value can change dynamically, as subsampling factor.
So, with all this in mind, rolling back to our starting point, I think a potentially better solution here is to switch from Constant
to DataSymbol
, as a DataSymbol
still allows user overrides while not carrying any data explicitly, and so behaving as expected. Check the following out -- no surprises.
In [1]: from devito.types import Constant
In [2]: a = Constant(name='a')
In [3]: a1 = Constant(name='a1')
In [4]: a == a1
Out[4]: False
...
In [8]: from devito.types.basic import DataSymbol
In [9]: b = DataSymbol(name='b')
In [10]: b1 = DataSymbol(name='b')
In [11]: b == b1
Out[11]: True
In [12]: b.data
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[12], line 1
----> 1 b.data
AttributeError: 'DataSymbol' object has no attribute 'data'
for maximum neatness, we could still have a user-provided Constants as factors should still be supported for backwards compatibility obviously |
Well, that's the issue, it needs to carry some, forcing the user to provide the value at |
Also you need |
05ce88e
to
3ce097c
Compare
else: | ||
raise ValueError("factor must be an integer or integer Constant") | ||
|
||
if self._factor is not None: | ||
# Always make the factor symbolic to allow overrides with different factor. | ||
self._symbolic_factor = symbolic_factor or \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does this need to be an instance attribute? just like for example symbolic_size
or symbolic_max
are cached_property, can (should) this not be the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need it there so that it uses the name of the input Constant
when one is used for backward compatibility. Can't do that in a cached_property.
# Parent dimension define the interval | ||
fact = self._factor.data if self._factor is not None else 1 | ||
def _arg_values(self, interval, grid=None, args=None, **kwargs): | ||
if self.symbolic_factor is not None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assuming it's possible to turn symbolic_factor into a cached_property, here we would need if self.factor. is not None
|
||
def __init_finalize__(self, name, parent=None, factor=None, condition=None, | ||
indirect=False, **kwargs): | ||
indirect=False, symbolic_factor=None, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docstring needs updating since symbolic_factor
now included in kwargs. How is symbolic_factor
different to factor
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
factor
is just the number it was created with, symbolic_factor
is the symbol in the code but it's a plain Scalar that doesn't carry data and can be passed at apply.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Does it _rebuild
correctly? I seem to remember that there is still an issue where rebuilding a ConditionalDimension
with no factor introduces a factor of one unless that got patched when I wasn't looking
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This rebuild issue been patch a while back yes
3ce097c
to
7b48777
Compare
@@ -305,7 +305,7 @@ def spacing_map(self): | |||
# Special case subsampling: `Grid.dimensions` -> (xb, yb, zb)` | |||
# where `xb, yb, zb` are ConditionalDimensions whose parents | |||
# are SpaceDimensions | |||
mapper[d.root.spacing] = s/self.dtype(d.factor.data) | |||
mapper[d.root.spacing] = s/self.dtype(d.factor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my last worry, after looking at this line, is that this set of changes might somehow break user code, because now .factor
is a different thing, while the user may have expected a Constant if a Constant was supplied
7b48777
to
5c268dc
Compare
5c268dc
to
f59a4fe
Compare
No description provided.