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

Create dispatch system for executors #3263

Merged
merged 42 commits into from
Nov 13, 2024
Merged

Create dispatch system for executors #3263

merged 42 commits into from
Nov 13, 2024

Conversation

csarofeen
Copy link
Collaborator

@csarofeen csarofeen commented Oct 24, 2024

Separate out ExprEvalExecutor and HostIrExecutor from what's now called KernelExecutor. Create a dispatch system for them as compile and run are simpler for the former two.

Also renamed instances of FusionExecutorCache to executor_cache, KernelExecutor to ke, ExprEvalExecutor to eee, and HostIrExecutor to hire. It makes this PR large, but was critical to refactor all the instances of these classes.

For review focus on the following files:
csrc/host_ir/executor.[cpp,h]
csrc/runtime/executor.[cpp,h]
csrc/runtime/executor_abstract.h
csrc/runtime/executor_dispatch.[cpp,h]
csrc/runtime/fusion_executor_cache.cpp
csrc/runtime/fusion_kernel_runtime.[cpp,h]

Remaining files are just renaming. I would break this into multiple PRs, but it would be difficult to do at this point.

@@ -845,13 +845,6 @@ bool Fusion::hasDynamicTransform() {
return !ir_utils::getTVsWithDynamicTransform(this).empty();
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Just moved this function to executor.cpp as it wasn't used anywhere else.

@@ -326,17 +326,15 @@ SegmentProfiler::SegmentProfiler(uint32_t id, bool cupti_disabled)
output_bytes_(0),
kernel_profile_state_(ProfilerState::Ready) {}

void SegmentProfiler::startCompile(int device) {
device_ = device;
void SegmentProfiler::startCompile() {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Separated out set device as a separate function. KernelExecutor knows device on compilation since runtime information is needed for it, the other executors set it in run.

@@ -22,6 +22,7 @@ namespace nvfuser {
//! \enum ProfilerState
//! \brief An enum used to represent the state of a profiling state machine
enum class ProfilerState {
None,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Just added this to initialize the state on construction.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I doubt this is needed. ProfilerState::Ready seems to be a good initial state already -- all reset* functions set the state to that. cc @kevinstephano

csrc/instrumentation.h Outdated Show resolved Hide resolved
inputs,
user_sched.fusion_id_,
user_sched.device_id_);
user_sched.scheduled_fusion.get(), inputs
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Need Ryan's advice here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@rdspring1 another place I could use your help, please see the comment below.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@rdspring1 Could you take a look here?

csrc/runtime/executor.cpp Outdated Show resolved Hide resolved
csrc/runtime/executor.cpp Outdated Show resolved Hide resolved
csrc/runtime/executor.cpp Outdated Show resolved Hide resolved
csrc/runtime/executor.cpp Outdated Show resolved Hide resolved
csrc/runtime/executor.cpp Outdated Show resolved Hide resolved
csrc/runtime/executor.cpp Outdated Show resolved Hide resolved
csrc/runtime/executor.cpp Outdated Show resolved Hide resolved
csrc/runtime/executor.cpp Outdated Show resolved Hide resolved
tests/cpp/test_alias.cpp Outdated Show resolved Hide resolved
…idevice/executor.[cpp,h] and rename to HostIrExecutor.
@samnordmann
Copy link
Collaborator

I think that the HostUnit alternative will not achieve anything more than what add_out and sum_out can achieve.

I think the HostUnit alternative gives fewer global reads/writes when the addition can be fused to the preceding kernel.

c = sum_H(a*b)  # H means along a host-parallel dimension

With the HostUnit alternative, each iteration reads a, reads b, reads c, computes c+a*b and writes that as the updated c.

With sum_out or add_out, each iteration reads a, reads b, writes a*b, reads a*b, reads c, computes c+a*b, and writes the updated c.

However here the accumulation across iteration is still done on a globally allocated buffer (c).

I think what you are describing here corresponds to fusing operations within the host for-loop's body, say into one HostUnit, which gives the classical benefit of fusing kernels. However, my point is that fusing across iterations is not possible, and the I/O of the for-loop's body (here, a, b, and c, but not a*b indeed) must be on global memory.

@wujingyue
Copy link
Collaborator

However, my point is that fusing across iterations is not possible

Agreed! I wasn't trying to argue about that.

@csarofeen
Copy link
Collaborator Author

@samnordmann @wujingyue this conversation seems pretty great, it'd be wonderful if you could capture it in a design doc.

@naoyam
Copy link
Collaborator

naoyam commented Nov 8, 2024

@Priya2698 Could you check the benchmark profiling with this PR? There should be no performance change, but since there's a lot of code changes, we should make sure everything works as expected.

@Priya2698
Copy link
Collaborator

@Priya2698 Could you check the benchmark profiling with this PR? There should be no performance change, but since there's a lot of code changes, we should make sure everything works as expected.

Are you interested in a complete sweep or only the host benchmarking? We can run a complete sweep on the CI.
CC: @xwang233

@naoyam
Copy link
Collaborator

naoyam commented Nov 8, 2024

@Priya2698 Could you check the benchmark profiling with this PR? There should be no performance change, but since there's a lot of code changes, we should make sure everything works as expected.

Are you interested in a complete sweep or only the host benchmarking? We can run a complete sweep on the CI. CC: @xwang233

Please do a complete sweep just in case. Either A100 or H100. Not necessary to check both.

@Priya2698
Copy link
Collaborator

@Priya2698 Could you check the benchmark profiling with this PR? There should be no performance change, but since there's a lot of code changes, we should make sure everything works as expected.

Are you interested in a complete sweep or only the host benchmarking? We can run a complete sweep on the CI. CC: @xwang233

Please do a complete sweep just in case. Either A100 or H100. Not necessary to check both.

Got it, we will need to use CI resources then since the runs time out due to dlcluster time limits.
@xwang233 will be able to help. We can run preferably run on A100 due to more availability.

@xwang233
Copy link
Collaborator

xwang233 commented Nov 8, 2024

!test --pybench-full

…r user scheduling. (#3357)

The goal is to set `fusion_id` and `device_id` when creating
`KernelExecutor` for `UserSchedule. Previously, it was set during
`FusionExecutor::compileFusion`. This PR is stacked on
`executor_dispatch`

**Changes to `UserSchedule` cache system:**
**Current:** The map key is the integer value of input arguments. The
vector is of size `device id`.
`std::unordered_map<size_t, std::vector<UserSchedule>>
user_def_schedules;`

**New:** The key to first map is the integer value of input arguments.
The key to second map is of `device`.

**Why?** We can set the the `fusion_id` and `device_id` in the
constructor of `UserSchedule` and `KernelExecutor`.
@naoyam
Copy link
Collaborator

naoyam commented Nov 12, 2024

@Priya2698 @xwang233 Could you please let us know how the benchmarking went?

@Priya2698
Copy link
Collaborator

@Priya2698 @xwang233 Could you please let us know how the benchmarking went?

Comparing the pipeline results to the latest nvfuser nightly results does not show any major difference: http://nv/eno
Please verify against nightly results, since weekly has additional inputs.

@naoyam
Copy link
Collaborator

naoyam commented Nov 12, 2024

Thanks. I don't see anything suspicious either.

Where can we find host benchmark results?

@xwang233
Copy link
Collaborator

Thanks. I don't see anything suspicious either.

Where can we find host benchmark results?

host latency benchmarks for this PR were executed with kernel_reuse disabled, so dynamic results might be inaccurate

@Priya2698
Copy link
Collaborator

Priya2698 commented Nov 13, 2024

I am seeing similar results for all cases except test_many_segments_host_benchmark for dynamic. This PR does not contain changes from PR #3388 so this is expected. Apart from that, I do not see any major deviations.

On A100-asus:

test_adaptive_layernorm_fwd:
Branch: main
Screenshot 2024-11-13 at 7 56 38 PM

Branch: This PR
Screenshot 2024-11-13 at 8 08 26 PM

test_many_segment_host_benchmark.py:
Branch: main
Screenshot 2024-11-13 at 7 57 16 PM
Branch: This PR
Screenshot 2024-11-13 at 8 08 55 PM

test_many_pointwise_ops.py
Branch: main
Screenshot 2024-11-13 at 7 56 18 PM

Branch: Current PR
Screenshot 2024-11-13 at 8 20 24 PM

@naoyam
Copy link
Collaborator

naoyam commented Nov 13, 2024

@csarofeen Everything looks good. I'll run the final CI just in case.

@naoyam
Copy link
Collaborator

naoyam commented Nov 13, 2024

!test

@naoyam naoyam merged commit 0f2f99e into main Nov 13, 2024
48 checks passed
@naoyam naoyam deleted the executor_dispatch branch November 13, 2024 22:44
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.

7 participants