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

[User Schedule] Add print functions for TensorViews and User Scheduled Fusions #2282

Merged
merged 9 commits into from
Jun 2, 2024

Conversation

rdspring1
Copy link
Collaborator

@rdspring1 rdspring1 commented May 22, 2024

This PR adds two functions for debugging user scheduled fusions in python frontend.

std::string FusionDefinition::userScheduleIr() returns the user scheduled fusion IR.

Usage:

class SomeFusion(FusionDefinition):
    def definition(self):
        # create some fusion

    def schedule(self):
        print(fd.sched.user_schedule_ir())

to_string(python_frontend::Tensor) returns the string representation for its corresponding TensorView.

Usage:

print(fd.sched.to_string(some_tensor))

PR List:

  1. [User Schedule] Add print functions for TensorViews and User Scheduled Fusions #2282 <<< YOU ARE HERE
  2. [User Schedule] Expand ParallelType enum support #2283
  3. [User Schedule] Add cacheBefore, cacheAfter, and setMemoryType #2284
  4. [User Schedule] Implement transform_like and parallelize_like #2285
  5. [User Schedule] Add inline_most and inline_at #2286
  6. [User Schedule] Support filtering tensors according to some predicate function #2287
  7. Select CompileParams for TMA operations automatically at compile-time #2288

Copy link
Collaborator

@naoyam naoyam left a comment

Choose a reason for hiding this comment

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

This seems really useful. Thanks! I'll let others chime in on the Python interface itself, but could you also create some documentation? Do we already have a doc for the Python interface? If so, I suppose that should be updated.

@wujingyue wujingyue removed their request for review May 29, 2024 17:33
@wujingyue
Copy link
Collaborator

I'm behind for many things this week, so sorry for not being able to review this series of PRs. I think the line of the work (especially #2285) could potentially help @cowanmeg manually shard the Transformer block (#2199) more easily.

@@ -2777,6 +2781,20 @@ void initNvFuserPythonBindings(PyObject* module) {
py::class_<FusionDefinition::SchedOperators> nvf_sched(
fusion_def, "SchedOperators");
nvf_sched.def(py::init<FusionDefinition*>());
nvf_sched.def(
"to_string",
Copy link
Collaborator

Choose a reason for hiding this comment

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

nitpick: let's try to hide this by naming it properly with a leading _ like the other print things.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We wrap the print functions for FusionDefinition in nvfuser/__init__.py like https://github.com/NVIDIA/Fuser/blob/main/nvfuser/__init__.py#L246-L253. I'm not sure if we need the _ if it is a public function for this case.

Copy link
Collaborator

Choose a reason for hiding this comment

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

sorry for nitpicking on this one. I wasn't sure that our intention is to have this as a public API. It's a bit confusing for the to_string on a pybind Tensor class, since we do have __repr__ for the bind class, but this to_string is actually printing out the TensorView.

But that's just a nitpicking. I'm find with keeping this as-is.

csrc/python_frontend/fusion_definition.cpp Outdated Show resolved Hide resolved
@@ -593,6 +593,10 @@ void initNvFuserPythonBindings(PyObject* module) {
"_fusion_ir",
[](FusionDefinition& self) { return self.fusionIr(); },
py::return_value_policy::reference)
.def(
"_user_schedule_ir",
Copy link
Collaborator

Choose a reason for hiding this comment

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

IIUC, userScheduleIr can be safely called after a single execution with a custom schedule.

But we can also safely call it outside of def schedule(self): as well, my question is, is that an intended usage? Otherwise, if we are only supposed to use it inside schedule, we might as well keep this method under nvf_sched instead?

I'm not pushing strongly against this, but if we decide to keep the API as-is, I'd highly recommend relaxing the NVF_CHECK above with proper warning/recommendation on proper usage.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It could be useful to print fusion IR outside of the schedule function. I'll keep it and replace the NVF_CHECK with a string message.

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 moved the method to nvf_sched since user_sched_ is reset after finalize_schedule is called and is not available outside of def schedule.

Copy link
Collaborator

@jjsjann123 jjsjann123 left a comment

Choose a reason for hiding this comment

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

LGTM, some minor comments on user experience but let's clean up in following PRs.

@@ -2777,6 +2781,20 @@ void initNvFuserPythonBindings(PyObject* module) {
py::class_<FusionDefinition::SchedOperators> nvf_sched(
fusion_def, "SchedOperators");
nvf_sched.def(py::init<FusionDefinition*>());
nvf_sched.def(
"to_string",
Copy link
Collaborator

Choose a reason for hiding this comment

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

sorry for nitpicking on this one. I wasn't sure that our intention is to have this as a public API. It's a bit confusing for the to_string on a pybind Tensor class, since we do have __repr__ for the bind class, but this to_string is actually printing out the TensorView.

But that's just a nitpicking. I'm find with keeping this as-is.

@@ -228,6 +228,18 @@ std::string FusionDefinition::fusionIr() {
return ss.str();
}

std::string FusionDefinition::userScheduleIr() {
NVF_CHECK(id().has_value(), "Invalid fusion definition!");
Copy link
Collaborator

Choose a reason for hiding this comment

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

IIUC, vvv

  class SomeFusion(FusionDefinition):
    def definition(self):
        # create some fusion
    def schedule(self):
        print(self._user_schedule_ir())

  fd = SomeFusion()
  fd.user_schedule_ir() # it would assert here with `Invalid fusion definition`?

one more nitpicking, this really isn't your problem, but we can probably use a better error message and probably a warning rather than an assert. I think all the other FusionDefinition methods defined in nvfuser/__init__.py suffers the same.

Keep it as-is in this PR. But I think we can use a clean up PR afterwards. Wdyt @kevinstephano

Copy link
Collaborator

@jjsjann123 jjsjann123 left a comment

Choose a reason for hiding this comment

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

One last question: What's the story with version bump?

Since we are only adding new APIs here, I'm OK with keeping the version as-is and bump then towards the end of the stacked PRs. (and pretend that they do not exist).

One other thing is, let's add a test as well.

@rdspring1
Copy link
Collaborator Author

I updated the version and add some tests.

@rdspring1 rdspring1 requested a review from jjsjann123 May 30, 2024 00:39
@rdspring1
Copy link
Collaborator Author

!build

@rdspring1 rdspring1 merged commit 3e69e7c into main Jun 2, 2024
37 checks passed
@rdspring1 rdspring1 deleted the user_print branch June 2, 2024 16:04
zasdfgbnm pushed a commit that referenced this pull request Jun 5, 2024
…d Fusions (#2282)

This PR adds two functions for debugging user scheduled fusions in
python frontend.

`std::string FusionDefinition::userScheduleIr()` returns the user
scheduled fusion IR.

Usage:
```python
class SomeFusion(FusionDefinition):
    def definition(self):
        # create some fusion

    def schedule(self):
        print(fd.sched.user_schedule_ir())
```


`to_string(python_frontend::Tensor)` returns the string representation
for its corresponding TensorView.

Usage:
```python
print(fd.sched.to_string(some_tensor))
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Python API Issues related to the Python API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants