如何在Ray的Actor间共享对象?多Actor如何读写同一对象以避免ray.get产生新副本?
Great question! The ray.put()/ray.get() workflow you mentioned does create copies of the object each time, which won't work for true shared read-write access between Actors. Let's walk through the two most reliable approaches to solve this in Ray:
1. Use Ray's Shared Memory Objects
Ray provides built-in utilities for shared memory that let multiple Actors access the same underlying data without copying it. This is perfect for cases where you need low-overhead shared access, though you'll need to handle synchronization yourself if multiple Actors are writing.
Here's a quick example with a numpy array:
import ray import numpy as np from ray.util.shared_memory import create_shared_memory, get_shared_memory ray.init() # Create a shared memory-backed numpy array shared_arr = create_shared_memory(np.zeros(1)) @ray.remote class WorkerActor: def write_to_shared(self, shared_ref): # Access the shared array arr = get_shared_memory(shared_ref) arr[0] += 1 # Modify the shared data directly return arr[0] def read_shared(self, shared_ref): arr = get_shared_memory(shared_ref) return arr[0] # Spawn actors and pass the shared memory reference actor1 = WorkerActor.remote() actor2 = WorkerActor.remote() # Both actors modify and read the same shared array print(ray.get(actor1.write_to_shared.remote(shared_arr))) # Output: 1 print(ray.get(actor2.write_to_shared.remote(shared_arr))) # Output: 2 print(ray.get(actor1.read_shared.remote(shared_arr))) # Output: 2
2. Use a Dedicated "State Manager" Actor
If you need safe, synchronized access (to avoid race conditions from concurrent writes), create a single Actor that holds the shared object and exposes methods to read/write it. Since Actors execute tasks sequentially, this naturally handles synchronization for you.
Example:
import ray import numpy as np ray.init() @ray.remote class SharedStateManager: def __init__(self): self.shared_obj = np.zeros(1) def update(self, value): self.shared_obj[0] = value return self.shared_obj[0] def increment(self): self.shared_obj[0] += 1 return self.shared_obj[0] def get(self): return self.shared_obj[0] @ray.remote class WorkerActor: def __init__(self, state_manager_ref): self.state_manager = state_manager_ref def do_write(self, value): return ray.get(self.state_manager.update.remote(value)) def do_increment(self): return ray.get(self.state_manager.increment.remote()) def do_read(self): return ray.get(self.state_manager.get.remote()) # Create the state manager first state_manager = SharedStateManager.remote() # Pass the state manager reference to workers actor1 = WorkerActor.remote(state_manager) actor2 = WorkerActor.remote(state_manager) # All operations go through the state manager, ensuring safe access print(ray.get(actor1.do_increment.remote())) # Output: 1 print(ray.get(actor2.do_increment.remote())) # Output: 2 print(ray.get(actor1.do_read.remote())) # Output: 2
Key Notes
- Shared Memory: Best for high-performance scenarios where you can manage synchronization (e.g., using locks if needed)
- State Manager Actor: Best for safety and simplicity, especially when concurrent writes are common (the sequential execution of Actor methods prevents race conditions)
内容的提问来源于stack exchange,提问作者Om Solari

