Skip to content

[ci] chore: add some NPU's UT/ST#6831

Open
daikang6 wants to merge 21 commits into
verl-project:mainfrom
daikang6:main
Open

[ci] chore: add some NPU's UT/ST#6831
daikang6 wants to merge 21 commits into
verl-project:mainfrom
daikang6:main

Conversation

@daikang6

Copy link
Copy Markdown
Contributor

What does this PR do?

Use cases benchmarking GPUs,add some NPU's UT/ST

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 refactors the training runner by extracting a BaseTaskRunner class from TaskRunner to support local and NPU unit/system testing. The review feedback points out that the base class still contains hardcoded Ray dependencies and that the core training workflow is implemented in the subclass, which limits reusability. It suggests abstracting worker wrapping and moving the core workflow to the base class to make it truly environment-agnostic.

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 on lines +30 to 33
class BaseTaskRunner:
def __init__(self):
self.role_worker_mapping = {}
self.mapping = {}

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

Design Feedback: Decoupling BaseTaskRunner from Ray for UT/ST Support

The extraction of BaseTaskRunner is a good step toward supporting local/NPU unit and system testing. However, the current implementation has two major design limitations that hinder its reusability and testability:

  1. Hardcoded Ray Dependencies in the Base Class:
    Methods like add_actor_rollout_worker and add_critic_worker inside BaseTaskRunner still directly call ray.remote(...) and use Ray-specific classes (e.g., RayWorkerGroup). This means any non-Ray or local subclass of BaseTaskRunner will still be forced to spin up Ray actors, defeating the purpose of an environment-agnostic base class.

  2. Monolithic and Non-Reusable run Method:
    BaseTaskRunner.run is defined as a no-op (pass), while the entire PPO training workflow is implemented inside TaskRunner.run. If you want to create a local/NPU runner subclass to run the actual training loop, you would have to duplicate the entire run method.


Suggested Refactoring

To make BaseTaskRunner truly reusable and testable:

1. Abstract the Worker Wrapping

Introduce a helper method in BaseTaskRunner to wrap worker classes, and override it in TaskRunner to apply ray.remote:

# In BaseTaskRunner
def _wrap_worker(self, worker_cls):
    return worker_cls

# In TaskRunner
def _wrap_worker(self, worker_cls):
    return ray.remote(worker_cls)

Then, update the worker registration in BaseTaskRunner to use this helper:

# In BaseTaskRunner.add_actor_rollout_worker
self.role_worker_mapping[role] = self._wrap_worker(actor_rollout_cls)

2. Move the Core Workflow to the Base Class

Move the implementation of run from TaskRunner to BaseTaskRunner, and abstract the Ray-specific components (like RayPPOTrainer and ResourcePoolManager) into factory methods that can be overridden by subclasses.

@daikang6 daikang6 reopened this Jun 24, 2026
Comment thread tests/models/test_engine.py Outdated
@pytest.mark.parametrize("strategy", ["fsdp", "fsdp2"])
def test_critic_engine(strategy):
device_count = torch.cuda.device_count()
if device_name == "cuda":

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

可以调用verl/verl/utils/device.py里面的get_device_name,来避免if分支的判断

Comment thread tests/models/test_engine.py Outdated
hf_output = hf_model(input_ids.cuda(), attention_mask=attention_mask.cuda())
hf_values = hf_output.logits[:, -response_length - 1 : -1, :].float().squeeze(-1).cpu()
elif device_name == "npu":
with torch.device("npu"), torch.autocast(device_type="npu", dtype=torch.bfloat16):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这里也是,可以把device_type用变量来传入

Comment thread tests/models/test_engine.py Outdated
model = "~/models/HuggingFaceTB/SmolLM2-135M-Instruct"
else:
model = "~/models/Qwen/Qwen2.5-0.5B"
model = "/mnt/weight/Qwen2.5-0.5B"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

路径不对,不要用本地路径

Comment thread tests/models/test_engine.py Outdated
device_count = torch.cuda.device_count()
if device_name == "cuda":
device_count = torch.cuda.device_count()
elif device_name == "npu":

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

可以调用verl/verl/utils/device.py里面的get_device_name,来避免if分支的判断

wucong25
wucong25 previously approved these changes Jun 26, 2026
Comment thread tests/models/test_engine.py Outdated
from verl.single_controller.ray import RayClassWithInitArgs, RayResourcePool, RayWorkerGroup
from verl.trainer.config import CheckpointConfig
from verl.utils import tensordict_utils as tu
from verl.utils.device import *

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这里为啥需要import *, 最好用到了什么函数导入什么函数,按需导入

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants