Repository: ray-project/ray
Pull request: [Core][Doc] Add Description for Named Placement Group to Require a Namespace
<!-- Thank you for your contribution! Please review https://github.com/ray-project/ray/blob/master/CONTRIBUTING.rst before opening a pull request. -->

<!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. -->

## Why are these changes needed?

This PR adds the description for named placement group to require a namespace. The corresponding code example is updated as well.

<!-- Please give a short summary of the change and the problem this solves. -->

## Related issue number
Closes https://github.com/ray-project/ray/issues/51149

<!-- For example: "Closes #1234" -->

## Checks

- [ ] I've signed off every commit(by using the -s flag, i.e., `git commit -s`) in this PR.
- [ ] I've run `scripts/format.sh` to lint the changes in this PR.
- [ ] I've included any doc changes needed for https://docs.ray.io/en/master/.
    - [ ] I've added any new APIs to the API Reference. For example, if I added a
           method in Tune, I've added it in `doc/source/tune/api/` under the
           corresponding `.rst` file.
- [ ] I've made sure the tests are passing. Note that there might be a few flaky tests, see the recent failures at https://flakey-tests.ray.io/
- Testing Strategy
   - [ ] Unit tests
   - [ ] Release tests
   - [ ] This PR is not tested :(


Problem statement:
[core] Named placement groups don't work
### What happened + What you expected to happen

On terminal 1:

```
In [1]: import ray

In [2]: from ray.util.placement_group import placement_group

In [3]: pg_inference = placement_group([{"CPU": 1}] * 2, name="inference")
2025-03-06 22:02:53,086	INFO worker.py:1655 -- Connecting to existing Ray cluster at address: 127.0.0.1:6379...
2025-03-06 22:02:53,091	INFO worker.py:1833 -- Connected to Ray cluster. View the dashboard at 127.0.0.1:8265

In [4]: pg_inference.ready()
Out[4]: ObjectRef(c8ef45ccd0112571ffffffffffffffffffffffff0100000001000000)

In [5]: ray.get(pg_inference.ready())
Out[5]: <ray.util.placement_group.PlacementGroup at 0x106bca440>
```
on terminal 2:

```
In [1]: import ray

In [2]: pg = ray.util.get_placement_group("inference")
2025-03-06 22:03:00,860	INFO worker.py:1655 -- Connecting to existing Ray cluster at address: 127.0.0.1:6379...
2025-03-06 22:03:00,864	INFO worker.py:1833 -- Connected to Ray cluster. View the dashboard at 127.0.0.1:8265
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[2], line 1
----> 1 pg = ray.util.get_placement_group("inference")

File ~/miniconda3/lib/python3.10/site-packages/ray/_private/client_mode_hook.py:141, in client_mode_wrap.<locals>.wrapper(*args, **kwargs)
    139     ref = f.remote(*args, **kwargs)
    140     return ray.get(ref)
--> 141 return func(*args, **kwargs)

File ~/miniconda3/lib/python3.10/site-packages/ray/util/placement_group.py:255, in get_placement_group(placement_group_name)
    251 placement_group_info = ray._private.state.state.get_placement_group_by_name(
    252     placement_group_name, worker.namespace
    253 )
    254 if placement_group_info is None:
--> 255     raise ValueError(
    256         f"Failed to look up placement group with name: {placement_group_name}"
    257     )
    258 else:
    259     return PlacementGroup(
    260         PlacementGroupID(hex_to_binary(placement_group_info["placement_group_id"]))
    261     )

ValueError: Failed to look up placement group with name: inference
```

cc @stephanie-wang @ruisearch42 

### Versions / Dependencies

master

### Reproduction script

(see above)

### Issue Severity

None

Hints from issue discussion:
Hi @MengjinYan , can you help take a look as oncall?
I took a look at the issue. 

It is seems that it is because for named placement group, you will need to specify a namespace (https://docs.ray.io/en/latest/ray-core/namespaces.html) for the placement group. This is because the query of the named placement group is by its name and the namespace. And without a namespace, an anonymous namespace will be set and the job will not have access to the placement group in another namespace.

Below are the scripts with namespace and terminal 2 can successfully find the placement group created by terminal 1:
* In terminal 1:
```
% python
Python 3.9.21 | packaged by conda-forge | (main, Dec  5 2024, 13:47:18) 
[Clang 18.1.8 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ray
>>> from ray.util.placement_group import placement_group
>>> ray.init(namespace="pg_namespace")
2025-03-10 00:06:48,726 INFO worker.py:1664 -- Connecting to existing Ray cluster at address: 127.0.0.1:6379...
2025-03-10 00:06:48,731 INFO worker.py:1842 -- Connected to Ray cluster. View the dashboard at 127.0.0.1:8265 
RayContext(dashboard_url='127.0.0.1:8265', python_version='3.9.21', ray_version='3.0.0.dev0', ray_commit='{{RAY_COMMIT_SHA}}')
>>> pg_inference = placement_group([{"CPU": 1}] * 2, name="inference")
>>> pg_inference.ready()
ObjectRef(c8ef45ccd0112571ffffffffffffffffffffffff0100000001000000)
>>> ray.get(pg_inference.ready())
<ray.util.placement_group.PlacementGroup object at 0x10cdaf940>
```
* In terminal 2:
```
% python
Python 3.9.21 | packaged by conda-forge | (main, Dec  5 2024, 13:47:18) 
[Clang 18.1.8 ] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import ray
>>> ray.init(namespace="pg_namespace")
2025-03-10 00:07:32,613 INFO worker.py:1664 -- Connecting to existing Ray cluster at address: 127.0.0.1:6379...
2025-03-10 00:07:32,620 INFO worker.py:1842 -- Connected to Ray cluster. View the dashboard at 127.0.0.1:8265 
RayContext(dashboard_url='127.0.0.1:8265', python_version='3.9.21', ray_version='3.0.0.dev0', ray_commit='{{RAY_COMMIT_SHA}}')
>>> ray.util.get_placement_group("inference")
<ray.util.placement_group.PlacementGroup object at 0x107964970>
```
Ok thanks! Can we add this to the documentation, as currently it's not clear:

https://docs.ray.io/en/latest/ray-core/scheduling/placement-group.html#advanced-named-placement-group
We need to improve the documentation.

Commit message: udpate link

Signed-off-by: Mengjin Yan <mengjinyan3@gmail.com>

Patch to review:
diff --git a/doc/source/ray-core/doc_code/placement_group_example.py b/doc/source/ray-core/doc_code/placement_group_example.py
index c8b16d70a1a05..e4d176e0dbd69 100644
--- a/doc/source/ray-core/doc_code/placement_group_example.py
+++ b/doc/source/ray-core/doc_code/placement_group_example.py
@@ -129,11 +129,12 @@ def ready(self):
 
 # __get_pg_start__
 # first_driver.py
-# Create a placement group with a global name.
-pg = placement_group([{"CPU": 1}], name="global_name")
+# Create a placement group with a unique name within a namespace.
+pg = placement_group([{"CPU": 1}], name="pg_name", namespace="pg_namespace")
 ray.get(pg.ready())
 
 # second_driver.py
-# Retrieve a placement group with a global name.
-pg = ray.util.get_placement_group("global_name")
+# Retrieve a placement group with a unique name within a namespace.
+ray.init(namespace="pg_namespace")
+pg = ray.util.get_placement_group("pg_name")
 # __get_pg_end__
diff --git a/doc/source/ray-core/scheduling/placement-group.rst b/doc/source/ray-core/scheduling/placement-group.rst
index cc7b9c7b49daf..1bb5318de25bd 100644
--- a/doc/source/ray-core/scheduling/placement-group.rst
+++ b/doc/source/ray-core/scheduling/placement-group.rst
@@ -585,12 +585,15 @@ child tasks and actors to the same placement group, specify ``PlacementGroupSche
 [Advanced] Named Placement Group
 --------------------------------
 
-A placement group can be given a globally unique name.
+You can give a unique name within a :ref:`namespace <namespaces-guide>` to a placement group.
 This allows you to retrieve the placement group from any job in the Ray cluster.
-This can be useful if you cannot directly pass the placement group handle to
+This is useful if you can't directly pass the placement group handle to
 the actor or task that needs it, or if you are trying to
 access a placement group launched by another driver.
-Note that the placement group is still destroyed if its lifetime isn't `detached`.
+Note that the placement group is still destroyed if its lifetime isn't `detached`. 
+Also, when creating or retrieving the named placement group, you need to specify the 
+:ref:`namespace <namespaces-guide>` associated with it. Otherwise, Ray assigns a anonymous :ref:`namespace <namespaces-guide>` which 
+makes it impossible to retrieve the placement group. 
 
 .. tab-set::
 


Code review comments:
diff_hunk: @@ -585,12 +585,15 @@ child tasks and actors to the same placement group, specify ``PlacementGroupSche
 [Advanced] Named Placement Group
 --------------------------------
 
-A placement group can be given a globally unique name.
+You can give a unique name within a :ref:`namespace <namespaces-guide>` to a placement group.
 This allows you to retrieve the placement group from any job in the Ray cluster.
-This can be useful if you cannot directly pass the placement group handle to
+This is useful if you can't directly pass the placement group handle to
 the actor or task that needs it, or if you are trying to
 access a placement group launched by another driver.
-Note that the placement group is still destroyed if its lifetime isn't `detached`.
+Note that the placement group is still destroyed if its lifetime isn't `detached`. 
+Also, when creating or retrieving the named placement group, you need to specify the 
+:ref:`namespace <namespaces-guide>` associated with it. Otherwise, Ray assigns a anonymous :ref:`namespace <namespaces-guide>` which 
path: doc/source/ray-core/scheduling/placement-group.rst
text: @user1:
```suggestion
:ref:`namespace <namespaces-guide>` associated with it. Otherwise, Ray assigns an anonymous :ref:`namespace <namespaces-guide>` which 
```