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

Enable user-defined map parameter types #1640

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open

Conversation

ThrudPrimrose
Copy link
Collaborator

@ThrudPrimrose ThrudPrimrose commented Sep 5, 2024

Adding param_types variable I can set the loop params to what I want.

I also remove the "auto" type to prefer the inferred type.

Using the inferred type instead of auto fixes the discrepancy of C++/CUDA inferred auto type and the inferred type between DaCe, where the discrepancy causes unnecessary implicit type conversion, resulting with a loss of performance.

…use auto in the for loop generated from the map
@ThrudPrimrose ThrudPrimrose changed the title Enable user-defined map parameter types, infer if not set and do not … Enable user-defined map parameter types Sep 5, 2024
if var in map_param_types.keys():
var_type = map_param_types[var]
else:
var_type = dtypes.result_type_of(infer_expr_type(r[0], sdfg.symbols), infer_expr_type(r[1], sdfg.symbols))
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it's better to use symbols_defined_at

dace/codegen/targets/cpu.py Outdated Show resolved Hide resolved
dace/sdfg/nodes.py Outdated Show resolved Hide resolved
@@ -793,7 +793,10 @@ def new_symbols(self, sdfg, state, symbols) -> Dict[str, dtypes.typeclass]:
result = {}
# Add map params
for p, rng in zip(self._map.params, self._map.range):
result[p] = dtypes.result_type_of(infer_expr_type(rng[0], symbols), infer_expr_type(rng[1], symbols))
if p in self.map.param_types.keys():
result[p] = dtypes.typeclass(self.map.param_types[p])
Copy link
Collaborator

Choose a reason for hiding this comment

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

why isn't the value type typeclass?

@@ -877,6 +880,7 @@ class Map(object):
# List of (editable) properties
label = Property(dtype=str, desc="Label of the map")
params = ListProperty(element_type=str, desc="Mapped parameters")
param_types = DictProperty(key_type=str, value_type=str, desc="Types of mapped parameters")
Copy link
Collaborator

Choose a reason for hiding this comment

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

shouldn't param types have a typeclass value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I had saved the typestrings set by the transformation as a Dict(str,str), such that if a user wants to give the type info as a part of a transformation then the user can just write the str, but in a sense, having the type be a typeclass has information value in the "param_types" parameter, I will update.

Comment on lines 932 to 933
gpu_force_syncthreads = Property(dtype=bool, desc="Force a call to the __syncthreads for the map", default=False)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Unrelated

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Must have sneaked in from the other PR, will delete it

@ThrudPrimrose
Copy link
Collaborator Author

I also need to check why the param type can be none sometimes (some tests failing)

@ThrudPrimrose
Copy link
Collaborator Author

There is one issue that I am currently trying to solve.
I can know change the map parameters' types, and can set them to be for example int, but I am having problems implementing the calls to the nested SDFGs seeing the correct types.

(I need to find a way for the method "new_symbols" of an interstate edge not to infer the type of the parameters if the parameter was introduced by a map parameter set by the user)

@ThrudPrimrose ThrudPrimrose marked this pull request as ready for review September 9, 2024 08:53
@ThrudPrimrose ThrudPrimrose marked this pull request as draft September 9, 2024 09:39
@ThrudPrimrose ThrudPrimrose marked this pull request as ready for review September 11, 2024 12:00
Copy link
Collaborator

@tbennun tbennun left a comment

Choose a reason for hiding this comment

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

Good addition, thank you! Two things are missing:

  1. My comment on symbols_defined_at (which should be computed as seldomly as possible)
  2. Missing unit test with types (maybe even an additional test that would fail with auto, as you now changed the behavior of codegen even in the default case)

Also, you do not have to keep merging with master, the merge queue will do that for you. Every merge puts an unnecessary burden on the CI queue.

Comment on lines 1933 to 1934
var_type = dtypes.result_type_of(infer_expr_type(r[0], state_dfg.symbols_defined_at(node)),
infer_expr_type(r[1], state_dfg.symbols_defined_at(node)))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please compute this once, preferably outside the loop of node.map.range. symbols_defined_at can be an expensive function. Thanks!

@@ -1601,6 +1601,7 @@ def add_nested_sdfg(
schedule=dtypes.ScheduleType.Default,
location=None,
debuginfo=None,
symbol_type_mapping: Dict[str, dtypes.typeclass] = None
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
symbol_type_mapping: Dict[str, dtypes.typeclass] = None
symbol_type_mapping: Dict[str, dtypes.typeclass] = None,

@ThrudPrimrose
Copy link
Collaborator Author

ThrudPrimrose commented Sep 16, 2024

Good addition, thank you! Two things are missing:

1. My comment on symbols_defined_at (which should be computed as seldomly as possible)

2. Missing unit test with types (maybe even an additional test that would fail with `auto`, as you now changed the behavior of codegen even in the default case)

Also, you do not have to keep merging with the master; the merge queue will do that for you. Every merge puts an unnecessary burden on the CI queue.

I will update the changes according to your comments. Thanks for pointing out the merge queue.

Since auto was only used in a loop, the type of the loop variable depends on the type used in the loop condition. The auto case will never produce code that does not compile unless we compile with -Wconversion -Werror.
However, I can create test cases where the SDFG will produce incorrect results. I will do that (and try to find couple of good test cases).

I have looked at the tests. No hard-coded SDFGs are used in the tests. I should create any SDFG I use through the API or a front-end, right?

@tbennun
Copy link
Collaborator

tbennun commented Sep 16, 2024

@ThrudPrimrose First of all, many tests use the SDFG API (e.g., add_edge_pair_test.py, you should use that.

Second, for a wrong test case, a simple for loop with a mismatch in start/end types will run forever if not written correctly. See the following example (which one can write in dace): https://godbolt.org/z/YW5xsP51x

@ThrudPrimrose
Copy link
Collaborator Author

Since there is no auto type, it is hard to create one that fails due to auto.
When I tried with auto, having auto I = 0; I <N with N being an unsigned long long variable results with I being an int and causing issues.

I can easily create a test that mimics this behaviour by forcing the type of the variable. Then I can run it with subprocess and check for segfaults, should I do that or these tests should be enough?

@tbennun
Copy link
Collaborator

tbennun commented Oct 10, 2024

What I meant was to have a test that would fail if we generated auto. Obviously all the tests will now pass. :)

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.

2 participants