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

misc: various Dimension internal fixes #2205

Merged
merged 7 commits into from
Sep 20, 2023
Merged

misc: various Dimension internal fixes #2205

merged 7 commits into from
Sep 20, 2023

Conversation

mloubout
Copy link
Contributor

@mloubout mloubout commented Sep 11, 2023

Fixes #2204
Fixes #2132
Fixes #2206
Fixes issue with ConditionalDimension range from @ccuetom

@mloubout mloubout force-pushed the misc-issues branch 2 times, most recently from 6ad85cf to 03c25b7 Compare September 11, 2023 13:52
@mloubout mloubout changed the title api: always use conditional dimension for interpolation radius dim misc: various Dimension internal fixes Sep 11, 2023
@mloubout mloubout added the API api (symbolics, types, ...) label Sep 11, 2023
@mloubout mloubout force-pushed the misc-issues branch 3 times, most recently from d09401b to 1519665 Compare September 11, 2023 15:23
@codecov
Copy link

codecov bot commented Sep 11, 2023

Codecov Report

Merging #2205 (97f1cc8) into master (5eaad80) will increase coverage by 0.00%.
The diff coverage is 91.85%.

@@           Coverage Diff           @@
##           master    #2205   +/-   ##
=======================================
  Coverage   87.08%   87.08%           
=======================================
  Files         228      228           
  Lines       40611    40700   +89     
  Branches     7429     7454   +25     
=======================================
+ Hits        35367    35445   +78     
- Misses       4644     4652    +8     
- Partials      600      603    +3     
Files Changed Coverage Δ
tests/test_gpu_openacc.py 5.66% <0.00%> (-0.04%) ⬇️
tests/test_gpu_openmp.py 4.23% <ø> (ø)
tests/test_mpi.py 99.18% <0.00%> (ø)
tests/test_operator.py 97.54% <0.00%> (-0.19%) ⬇️
devito/core/autotuning.py 93.50% <50.00%> (-0.41%) ⬇️
devito/builtins/initializers.py 91.41% <60.00%> (-1.05%) ⬇️
devito/tools/data_structures.py 71.68% <60.00%> (-0.99%) ⬇️
devito/ir/stree/algorithms.py 91.55% <100.00%> (+0.16%) ⬆️
devito/mpi/halo_scheme.py 93.05% <100.00%> (+0.07%) ⬆️
devito/operations/interpolators.py 98.12% <100.00%> (+0.09%) ⬆️
... and 11 more

@mloubout mloubout force-pushed the misc-issues branch 6 times, most recently from 2dd25ba to 8ae1f5f Compare September 15, 2023 13:46
@mloubout mloubout force-pushed the misc-issues branch 8 times, most recently from 610eeb2 to 7d2abb3 Compare September 16, 2023 02:13
@@ -209,8 +209,11 @@ def init_time_bounds(stepper, at_args, args):
else:
at_args[dim.max_name] = at_args[dim.min_name] + options['squeezer']
if dim.size_name in args:
# May need to shrink to avoid OOB accesses
at_args[dim.max_name] = min(at_args[dim.max_name], args[dim.max_name])
if isinstance(args[dim.size_name], range):
Copy link
Contributor

Choose a reason for hiding this comment

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

if not isinstance(...):
   # May need to shrink to avoid OOB accesses
   at_args[dim.max_name] = min(at_args[dim.max_name], args[dim.max_name])

@@ -380,5 +394,6 @@ def interpolation_coeffs(self):
@property
def _weights(self):
ddim, cdim = self.interpolation_coeffs.dimensions[1:]
return Mul(*[self.interpolation_coeffs.subs({ddim: ri, cdim: rd-rd.symbolic_min})
return Mul(*[self.interpolation_coeffs.subs({ddim: ri,
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpicking
for better readability, can we introduce mapper = {ddim: ....} on the line above?

@@ -584,6 +590,9 @@ def _prepare_arguments(self, autotune=None, **kwargs):
if configuration['mpi']:
raise ValueError("Multiple Grids found")
try:
# Take biggest grid, i.e discard grids with subdimensions
grids = {g for g in grids if not any(d.is_Sub for d in g.dimensions)}
Copy link
Contributor

Choose a reason for hiding this comment

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

this needs to be better abstracted in my opinion

I wonder whether we could have a SubGrid object (returned via __new__) to capture subsampled grids. And dramatically simplify our lives here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My main though is that this needs to be part of the Function on subdomain overall, this is a temporary fix for arg processing

Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if we drop this line and modify the one above as

            discretizations = {g for g in discretizations
                                if not any(d.is_Sub for d in g.dimensions)}

This should be enough to filter away the Subdomain grids?

Also: can we not at least add a property to Grid such as g.is_subdomain or g.is_domain or I don't know what name would be better. I feel having properties as opposed to peeking at the individual dimensions would be neater

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This should be enough to filter away the Subdomain grids?

No this will create issue for example if there is only one "sub-grid" this would end up empty and leads to missing arguments.

But looks like it's a duplicate from above now might be able to remove that one.

@@ -94,7 +94,7 @@ def __init_finalize__(self, *args, function=None, **kwargs):
# a reference to the user-provided buffer
self._initializer = None
if len(initializer) > 0:
self.data_with_halo[:] = initializer
self.data_with_halo[:] = initializer[:]
Copy link
Contributor

Choose a reason for hiding this comment

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

interesting, what's the difference here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No difference, just debug leftover, the issue was calling __init_finalize__ before setting newobj.function above, needed for first touch init. Slightly safer in case of shape differences though for weird (1, n)/(n, 1) shape where someone might give and (n,) vector

Copy link
Contributor

Choose a reason for hiding this comment

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

just being paranoid here... are we completely sure both the performance and the semantics of this assignment are exactly the same as master, except for that corner case u mention above?

Copy link
Contributor

Choose a reason for hiding this comment

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

I worry the new one might be slightly slower

Copy link
Contributor Author

Choose a reason for hiding this comment

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

[:] is just a view it has no performance impact.

Copy link
Contributor

Choose a reason for hiding this comment

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

well the view gets created, so it's not really 0 impact.... but yeah, I agree it's gonna be 0.0000001 in practice 😬

@mloubout mloubout force-pushed the misc-issues branch 4 times, most recently from 227730a to 47f6154 Compare September 18, 2023 20:16
@mloubout mloubout force-pushed the misc-issues branch 2 times, most recently from 963ec1b to fa1a7ac Compare September 19, 2023 14:46
devito/ir/stree/algorithms.py Outdated Show resolved Hide resolved
@@ -147,6 +147,12 @@ def preprocess(clusters, options=None, **kwargs):
found = []
for c1 in list(queue):
distributed_aindices = c1.halo_scheme.distributed_aindices
h_indices = set().union(*[(d, d.root)
Copy link
Contributor

Choose a reason for hiding this comment

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

For homogeneity with the rest of the code below, I would rather write:

distributed_aindices = c1.halo_scheme.distributed_aindices
loc_indices = c1.halo_scheme.loc_indices

all_loc_indices = set().union(*[d._defines for d in ...])
...

Note: I'm using _defines above

Copy link
Contributor

Choose a reason for hiding this comment

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

d_defines ?

devito/ir/stree/algorithms.py Show resolved Hide resolved
@@ -584,6 +590,9 @@ def _prepare_arguments(self, autotune=None, **kwargs):
if configuration['mpi']:
raise ValueError("Multiple Grids found")
try:
# Take biggest grid, i.e discard grids with subdimensions
grids = {g for g in grids if not any(d.is_Sub for d in g.dimensions)}
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if we drop this line and modify the one above as

            discretizations = {g for g in discretizations
                                if not any(d.is_Sub for d in g.dimensions)}

This should be enough to filter away the Subdomain grids?

Also: can we not at least add a property to Grid such as g.is_subdomain or g.is_domain or I don't know what name would be better. I feel having properties as opposed to peeking at the individual dimensions would be neater

@@ -336,7 +345,8 @@ def _is_offloadable(self, iet):
functions = FindSymbols().visit(iet)
buffers = [f for f in functions if f.is_Array and f._mem_mapped]
hostfuncs = [f for f in functions if not is_on_device(f, self.gpu_fit)]
return not (buffers and hostfuncs)

return not (hostfuncs and buffers)
Copy link
Contributor

Choose a reason for hiding this comment

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

leftover change?

devito/passes/iet/parpragma.py Show resolved Hide resolved
@@ -377,6 +375,12 @@ def _make_partree(self, candidates, nthreads=None):
ncollapsed=ncollapsed, nthreads=nthreads,
**root.args)
prefix = []
elif all(i.is_ParallelRelaxed for i in candidates) and nthreads is not None:
Copy link
Contributor

Choose a reason for hiding this comment

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

how about just

elif nthreads is not None:

actually, to mirror what we have in the first if, I might prefer:

else:
    if nthreads is None:
        nthreads = self.nthreads_nonaffine
        chunk_size = ...
        ...
    else:
        body = self.HostIteration(schedule='static', ...)
        prefix = []

@@ -94,7 +94,7 @@ def __init_finalize__(self, *args, function=None, **kwargs):
# a reference to the user-provided buffer
self._initializer = None
if len(initializer) > 0:
self.data_with_halo[:] = initializer
self.data_with_halo[:] = initializer[:]
Copy link
Contributor

Choose a reason for hiding this comment

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

just being paranoid here... are we completely sure both the performance and the semantics of this assignment are exactly the same as master, except for that corner case u mention above?

@@ -94,7 +94,7 @@ def __init_finalize__(self, *args, function=None, **kwargs):
# a reference to the user-provided buffer
self._initializer = None
if len(initializer) > 0:
self.data_with_halo[:] = initializer
self.data_with_halo[:] = initializer[:]
Copy link
Contributor

Choose a reason for hiding this comment

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

I worry the new one might be slightly slower

@@ -286,7 +284,7 @@ def test_cache_blocking_structure_optrelax_prec_inject():
'openmp': True,
'par-collapse-ncores': 1}))

assert_structure(op, ['t', 't,p_s0_blk0,p_s,rsx,rsy'],
assert_structure(op, ['t,p_s0_blk0,p_s', 't,p_s0_blk0,p_s,rsx,rsy'],
Copy link
Contributor

Choose a reason for hiding this comment

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

mmhh, why?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

CHange of parent hierachy in interp with rx... always being conditional

@@ -1446,7 +1452,7 @@ def symbolic_max(self):
def _arg_names(self):
return (self.min_name, self.max_name, self.name) + self.parent._arg_names

def _arg_defaults(self, _min=None, **kwargs):
def _arg_defaults(self, _min=None, size=None, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

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

why?

@@ -977,7 +983,7 @@ def symbolic_incr(self):
def bound_symbols(self):
return set(self.parent.bound_symbols)

def _arg_defaults(self, **kwargs):
def _arg_defaults(self, alias=None, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

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

useless change

@@ -1515,7 +1515,7 @@ def test_issue_1927(self, factor):

op = Operator(Eq(f, 1))

assert op.arguments()['time_M'] == 4*(save-1) # == min legal endpoint
assert op.arguments()['time_M'] == 4*save-1 # == min legal endpoint
Copy link
Contributor

Choose a reason for hiding this comment

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

I had a comment here which appearly I forgot to fire up...

anyway: was my old comment (min legal endpoint) wrong? or is the new one to be updated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The comment is correct, the value wasn't

Copy link
Contributor

Choose a reason for hiding this comment

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

ok

h_indices = set().union(*[(d, d.root)
for d in c1.halo_scheme.loc_indices])

# Skip if the Halo echange would end up outside its need iteration space
Copy link
Contributor

Choose a reason for hiding this comment

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

couple of typos here

args = kwargs['args'] = args.reduce_all()

# DiscreteFunctions may be created from CartesianDiscretizations, which in
# turn could be Grids or SubDomains. Both may provide arguments
discretizations = {getattr(kwargs[p.name], 'grid', None) for p in overrides}
discretizations.update({getattr(p, 'grid', None) for p in defaults})
discretizations.discard(None)
# Remove subgrids if multiple grids
if len(discretizations) > 1:
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to coin a term for any CartesianDiscretization that is not the main Grid

Also, we need to distinguish I think between SubDomain and SubGrid. The latter being a coarser representation of the (main) Grid

I don't exactly what names to use, but I feel an increasing need for a set of CartesianDiscretization attributes -- suitably overridden in the various subclasses -- along the lines of

is_root (is_main? is_domain?)
is_subdomain
is_subgrid

etc

and then here just g.is_domain for eaxmple

@@ -1515,7 +1515,7 @@ def test_issue_1927(self, factor):

op = Operator(Eq(f, 1))

assert op.arguments()['time_M'] == 4*(save-1) # == min legal endpoint
assert op.arguments()['time_M'] == 4*save-1 # == min legal endpoint
Copy link
Contributor

Choose a reason for hiding this comment

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

ok

Copy link
Contributor

@FabioLuporini FabioLuporini left a comment

Choose a reason for hiding this comment

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

GTG , thanks

@mloubout mloubout merged commit 237a4a8 into master Sep 20, 2023
32 checks passed
@mloubout mloubout deleted the misc-issues branch September 20, 2023 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API api (symbolics, types, ...) bug-py-minor
Projects
None yet
3 participants