Skip to content

[perf] feat: mstx profiler support schedule to mini batch#7105

Draft
mengchengTang wants to merge 1 commit into
verl-project:mainfrom
mengchengTang:npu_profiler_mini_batch
Draft

[perf] feat: mstx profiler support schedule to mini batch#7105
mengchengTang wants to merge 1 commit into
verl-project:mainfrom
mengchengTang:npu_profiler_mini_batch

Conversation

@mengchengTang

Copy link
Copy Markdown
Contributor

What does this PR do?

flow #7099

Checklist Before Starting

  • Search for similar PRs. Paste at least one query link here: ...
  • Format the PR title as [{modules}] {type}: {description} (This will be checked by the CI)
    • {modules} include fsdp, megatron, veomni, sglang, vllm, rollout, trainer, ci, training_utils, recipe, hardware, deployment, ray, worker, single_controller, misc, perf, model, algo, env, tool, ckpt, doc, data, cfg, reward, fully_async, one_step_off
    • If this PR involves multiple modules, separate them with , like [megatron, fsdp, doc]
    • {type} is in feat, fix, refactor, chore, test
    • If this PR breaks any API (CLI arguments, config, function signature, etc.), add [BREAKING] to the beginning of the title.
    • Example: [BREAKING][fsdp, megatron] feat: dynamic batching

Test

For changes that can not be tested by CI (e.g., algorithm implementation, new model support), validate by experiment(s) and show results like training curve plots, evaluation results, etc.

API and Usage Example

Demonstrate how the API changes if any, and provide usage example(s) if possible.

# Add code snippet or script demonstrating how to use this

Design & Code Changes

Demonstrate the high-level design if this PR is complex, and list the specific changes.

Checklist Before Submitting

Important

Please check all the following items before requesting a review, otherwise the reviewer might deprioritize this PR for review.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request adds support for scheduled profiling in the NPU profiler using torch_npu.profiler.schedule configurations (such as wait, warmup, active, repeat, and skip_first). This allows users to capture a subset of mini-batches during training update loops to reduce profiling data volume. The feedback suggests tracking the active schedule configuration globally at the class level (_active_schedule_kwargs) within NPUProfiler. This prevents potential AttributeError and state mismatches when different profiler instances (e.g., rollout and training workers) start and stop the process-wide NPU profiler.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread verl/utils/profiler/mstx_profile.py Outdated
Comment on lines +178 to +183
_define_count = 0
# Process-global handle to the currently running NPU profiler. torch_npu.profiler is
# process-wide, so a step() issued by one NPUProfiler instance (e.g. the inner actor
# TrainingWorker running the mini-batch loop) must advance the profiler that another
# instance started (e.g. the outer ActorRolloutRefWorker).
_active_prof = None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

To support safe start/stop operations across multiple NPUProfiler instances in the same process (e.g., ActorRolloutRefWorker and TrainingWorker), we should track the active schedule globally at the class level. This prevents instance-specific state mismatches when one instance stops a profiler started by another.

Suggested change
_define_count = 0
# Process-global handle to the currently running NPU profiler. torch_npu.profiler is
# process-wide, so a step() issued by one NPUProfiler instance (e.g. the inner actor
# TrainingWorker running the mini-batch loop) must advance the profiler that another
# instance started (e.g. the outer ActorRolloutRefWorker).
_active_prof = None
_define_count = 0
# Process-global handle to the currently running NPU profiler. torch_npu.profiler is
# process-wide, so a step() issued by one NPUProfiler instance (e.g. the inner actor
# TrainingWorker running the mini-batch loop) must advance the profiler that another
# instance started (e.g. the outer ActorRolloutRefWorker).
_active_prof = None
_active_schedule_kwargs = None

Comment on lines 223 to 237
def start(self, **kwargs):
role = kwargs.get("role", None)
if not self.discrete and NPUProfiler._define_count == 0:
self._schedule_kwargs = self._resolve_schedule_kwargs()
self.profile_npu = get_npu_profiler(
contents=self.profile_contents,
profile_level=self.profile_level,
profile_save_path=self.profile_save_path,
analysis=self.analysis,
role=role,
schedule=self._schedule_kwargs,
)
self.profile_npu.start()
NPUProfiler._active_prof = self.profile_npu
NPUProfiler._define_count += 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Store the active schedule at the class level (NPUProfiler._active_schedule_kwargs) when starting the profiler, so that any instance stopping the profiler can correctly determine if a schedule is active.

Suggested change
def start(self, **kwargs):
role = kwargs.get("role", None)
if not self.discrete and NPUProfiler._define_count == 0:
self._schedule_kwargs = self._resolve_schedule_kwargs()
self.profile_npu = get_npu_profiler(
contents=self.profile_contents,
profile_level=self.profile_level,
profile_save_path=self.profile_save_path,
analysis=self.analysis,
role=role,
schedule=self._schedule_kwargs,
)
self.profile_npu.start()
NPUProfiler._active_prof = self.profile_npu
NPUProfiler._define_count += 1
def start(self, **kwargs):
role = kwargs.get("role", None)
if not self.discrete and NPUProfiler._define_count == 0:
self._schedule_kwargs = self._resolve_schedule_kwargs()
self.profile_npu = get_npu_profiler(
contents=self.profile_contents,
profile_level=self.profile_level,
profile_save_path=self.profile_save_path,
analysis=self.analysis,
role=role,
schedule=self._schedule_kwargs,
)
self.profile_npu.start()
NPUProfiler._active_prof = self.profile_npu
NPUProfiler._active_schedule_kwargs = self._schedule_kwargs
NPUProfiler._define_count += 1

Comment on lines 239 to 248
def stop(self):
if not self.discrete and NPUProfiler._define_count == 1:
self.profile_npu.step()
# Continuous mode emits a trailing step to flush the final window; when a
# schedule is configured, stepping is driven per mini-batch instead.
if not self._schedule_kwargs:
self.step()
self.profile_npu.stop()
NPUProfiler._active_prof = None
self._schedule_kwargs = None
NPUProfiler._define_count -= 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

When stopping the profiler, use the class-level NPUProfiler._active_prof and NPUProfiler._active_schedule_kwargs instead of instance-specific variables. This avoids AttributeError when stop() is called on an instance that did not start the profiler, and ensures the correct schedule check is performed.

Suggested change
def stop(self):
if not self.discrete and NPUProfiler._define_count == 1:
self.profile_npu.step()
# Continuous mode emits a trailing step to flush the final window; when a
# schedule is configured, stepping is driven per mini-batch instead.
if not self._schedule_kwargs:
self.step()
self.profile_npu.stop()
NPUProfiler._active_prof = None
self._schedule_kwargs = None
NPUProfiler._define_count -= 1
def stop(self):
if not self.discrete and NPUProfiler._define_count == 1:
# Continuous mode emits a trailing step to flush the final window; when a
# schedule is configured, stepping is driven per mini-batch instead.
if not NPUProfiler._active_schedule_kwargs:
self.step()
if NPUProfiler._active_prof is not None:
NPUProfiler._active_prof.stop()
NPUProfiler._active_prof = None
NPUProfiler._active_schedule_kwargs = None
self._schedule_kwargs = None
NPUProfiler._define_count -= 1

@mengchengTang mengchengTang changed the title [perf] mstx profiler support schedule to mini batch [perf] feat: mstx profiler support schedule to mini batch Jul 21, 2026
@mengchengTang
mengchengTang force-pushed the npu_profiler_mini_batch branch from 6d5b7d2 to b35678c Compare July 22, 2026 02:09
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.

1 participant