💬

Rayシリーズ:Objects

に公開

今回はRayのコア機能であるObjectsについて調べてみました。シリーズについては以下のスクラップにまとめていますのでぜひご参考にしてください。

https://zenn.dev/akasan/scraps/73a90764c065d1

Ray Objectsとは?

過去の記事で見てきたように、RayにおいてはTaskとActorはオブジェクトを作成して計算されます。Rayではクラスタ内のどこにでもこれらの情報を格納でき、これらのことをリモートオブジェクトと呼び、それらを参照するためにオブジェクト参照を使用します。リモートオブジェクトはRayの分散共有メモリ上のオブジェクトストアにキャッシュされ、ノードに一つずつストアがあるようです。オブジェクト参照はオブジェクトに対するいわゆるポインタのような役割をし、一意な情報を保持しています。

後ほど見ていきますが、リモートオブジェクトは以下の二つの方法で作成することができます。

  • リモート関数の戻り値
  • ray.put()を利用

https://docs.ray.io/en/latest/ray-core/objects.html

実際に使ってみる

それでは実際に使っていきましょう。

環境構築

uvを使って環境を構築します。

uv init ray_objects -p 3.12
cd ray_actors
uv add ray

ray.put()を使った参照の作成

それでは早速オブジェクト参照を作ってみましょう。最も簡単に作るためにはray.put()を利用します。

import ray

y = 1
y_ref = ray.put(y)
print(y_ref)
print(ray.get(y_ref))

これを実行すると以下のようになります。結果を見ると、オブジェクト参照はObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000001e1f505)となっていて、ポインタ情報を持っていることがみて取れます。また、この値を参照するには以前もみたようにray.get(y_ref)のようにして参照しています。

2025-09-08 20:14:36,694	INFO worker.py:1951 -- Started a local Ray instance.
2025-09-08 20:14:36,698	INFO packaging.py:588 -- Creating a file package for local module '/Users/user/Documents/Blog/blog_materials/ray/ray_objects'.
2025-09-08 20:14:36,707	INFO packaging.py:380 -- Pushing file package 'gcs://_ray_pkg_8ce13c8fcaddb7fb.zip' (0.08MiB) to Ray cluster...
2025-09-08 20:14:36,708	INFO packaging.py:393 -- Successfully pushed file package 'gcs://_ray_pkg_8ce13c8fcaddb7fb.zip'.
ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000001e1f505)
1

注意点ですが、リモートオブジェクトはイミュータブル、つまり参照が作成された後に内容を変更することができません。

オブジェクト参照を引数として与える

オブジェクト参照はリモート関数の引数として与えることができます。例えば与えた3つの値を表示するような機能を実装してみましょう。

import ray 

@ray.remote
def show_numbers(a: int, b: int, c: int):
    print(f"{a=}, {b=}, {c=}")


ref = show_numbers.remote(1, 2, 3)
ray.get(ref)

a, b, c = ray.put(1), ray.put(2), ray.put(3)
ref = show_numbers.remote(a, b, c)
ray.get(ref)

これを実行すると、以下のようになります。数値そのままで受け渡してもオブジェクト参照を私ても、リモート関数ないで値を認識していることが確認できます。言い換えれば、オブジェクト参照をそのままリモート関数に受け渡すと、参照情報(ポインタ情報)ではなくその値として処理されることになります。

(raylet) warning: `VIRTUAL_ENV=/Users/user/Documents/Blog/blog_materials/ray/ray_objects/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
(raylet) Using CPython 3.12.9
(raylet) Creating virtual environment at: .venv
(raylet) Installed 26 packages in 207ms
(show_numbers pid=68457) a=1, b=2, c=3
(show_numbers pid=68457) a=1, b=2, c=3

例えば関数にオブジェクトの値ではなくオブジェクト参照そのものを受け渡したい場合があるとします。そのような場合は以下のようにオブジェクト参照をリストに内包した状態で受け渡します。

import ray 

@ray.remote
def show_numbers(items):
    print(f"{items=}")
    print(f"{ray.get(items)=}")


a, b, c = ray.put(1), ray.put(2), ray.put(3)
ref = show_numbers.remote([a, b, c])
ray.get(ref)

これを実行すると以下のような結果になります。結果を見ると、引数として与えられたitemsそのものを見るとオブジェクト参照そのものが表示されているのが確認できます。オブジェクトの値を参照するにはray.getを利用すれば確認できるので、必要に応じてこのような使い方も検討してみてください。

(raylet) warning: `VIRTUAL_ENV=/Users/user/Documents/Blog/blog_materials/ray/ray_objects/.venv` does not match the project environment path `.venv` and will be ignored; use `--active` to target the active environment instead
(raylet) Using CPython 3.12.9
(raylet) Creating virtual environment at: .venv
(raylet) Installed 26 packages in 196ms
(show_numbers pid=70526) items=[ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000001e1f505), ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000002e1f505), ObjectRef(00ffffffffffffffffffffffffffffffffffffff0100000003e1f505)]
(show_numbers pid=70526) ray.get(items)=[1, 2, 3]

どんなものをObjectsにできる?

ちょっと試しに色々とObjectsに登録できるか調べてみました

pydanticのBaseModel

結論:行ける

コード

import ray
from pydantic import BaseModel


class Model(BaseModel):
    x: int
    y: float


model = Model(x=10, y=10.5)
model_ref = ray.put(model)

model_get = ray.get(model_ref)
print(model_get)

実行結果

x=10 y=10.5
pytorchのモデル

結論:行ける

コード

import ray
from torch import nn


class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer1 = nn.Linear(10, 128)
        self.layer2 = nn.Linear(128, 256)
        self.layer3 = nn.Linear(256, 512)
        self.layer4 = nn.Linear(512, 1024)
        self.layer5 = nn.Linear(1024, 2048)

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        return self.layer5(x)


model = Model()

model_ref = ray.put(model)

model_get = ray.get(model_ref)
print(model_get)

実行結果

Model(
  (layer1): Linear(in_features=10, out_features=128, bias=True)
  (layer2): Linear(in_features=128, out_features=256, bias=True)
  (layer3): Linear(in_features=256, out_features=512, bias=True)
  (layer4): Linear(in_features=512, out_features=1024, bias=True)
  (layer5): Linear(in_features=1024, out_features=2048, bias=True)
)

まとめ

今回はRay Objectsを利用してみました。Ray Objectsを利用することで、同じオブジェクトストアを参照できる環境において変数などを共有することができます。分散処理を行にあたりその条件などを共有したりする場合に利用できるのではないでしょうか。

Discussion