Skip to content

Commit 91e2cdd

Browse files
adding remote state experiments
1 parent ed4b98c commit 91e2cdd

File tree

5 files changed

+231
-0
lines changed

5 files changed

+231
-0
lines changed

examples/stateful_create_actor.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
2+
# create_actor.py
3+
import ray
4+
5+
@ray.remote
6+
class StatefulActor:
7+
def __init__(self):
8+
self.state = {}
9+
self.invocation_count = 0
10+
11+
def set_value(self, key, value):
12+
self.state[key] = value
13+
14+
def get_value(self, key):
15+
return self.state.get(key, None)
16+
17+
def foobar(self):
18+
self.invocation_count +=1
19+
print("_______FOOOBAR________")
20+
print(self.invocation_count)
21+
self.set_value('invocation_count', self.invocation_count + 1)
22+
return "foobar"
23+
24+
# Use __setattr__ to set values dynamically
25+
def __setattr__(self, key, value):
26+
if key == 'state': # Ensure the actual state is set normally
27+
super().__setattr__(key, value)
28+
else:
29+
self.state[key] = value # Set the key-value pair in the state
30+
31+
# Use __getattr__ to get values dynamically
32+
def __getattr__(self, key):
33+
return self.get_value(key)
34+
35+
36+
# Initialize Ray and specify a namespace for easier reconnection
37+
ray.init()
38+
39+
# Create a detached actor under the namespace "my_namespace"
40+
actor = StatefulActor.options(
41+
name="stateful_actor",
42+
lifetime="detached",
43+
namespace="pymc-stateful-actor-dev"
44+
).remote()
45+
46+
# Set some initial state
47+
actor.set_value.remote("key1", "initial_value")
48+
49+
# Print the value to confirm it works
50+
print(ray.get(actor.get_value.remote("key1"))) # Outputs: initial_value
51+
52+
# You can now safely exit this program

examples/stateful_create_actorv2.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import ray
5+
6+
"""
7+
@ray.remote
8+
class StatefulActor:
9+
def __init__(self):
10+
super().__setattr__("state", {}) # Initialize state
11+
12+
def __setattr__(self, key, value):
13+
print('key: '+ key + ', value:', value)
14+
if key.startswith('_') or key == 'state':
15+
super().__setattr__(key, value)
16+
else:
17+
# Set the value using remote call
18+
ray.get(self.set_value.remote(key, value))
19+
20+
def __getattr__(self, key):
21+
print(key)
22+
# Dynamically fetch the value from the actor's state
23+
if key.startswith('_') or key == 'state':
24+
raise AttributeError(f"Attribute '{key}' not found") # Avoid infinite loop
25+
26+
return ray.get(self.get_value.remote(key))
27+
28+
def foobar(self):
29+
self.invocation_count +=1
30+
print("_______FOOOBAR________")
31+
print(self.invocation_count)
32+
#self.set_value('invocation_count', self.invocation_count + 1)
33+
return "foobar"
34+
35+
def set_value(self, key, value):
36+
self.state[key] = value
37+
38+
def get_value(self, key):
39+
return self.state.get(key, None)
40+
41+
"""
42+
import ray
43+
44+
@ray.remote
45+
class StatefulActor:
46+
def __init__(self):
47+
# Initialize internal state attributes
48+
self._state = {} # Use a private variable for dynamic attributes
49+
self.invocation_count = 0 # Internal state attribute
50+
51+
"""
52+
def __setattr__(self, key, value):
53+
print('set', key, value)
54+
# Allow normal assignment for internal attributes
55+
if '_' in key:
56+
# Directly set internal state attributes
57+
super().__setattr__(key, value)
58+
else:
59+
# Store dynamic attributes in the _state dictionary
60+
self._state[key] = value
61+
62+
def __getattr__(self, key):
63+
print('get', key)
64+
# Allow normal retrieval for internal attributes
65+
if '_' in key:
66+
return super().__getattribute__(key)
67+
# Return from dynamic state
68+
return self._state.get(key, None)
69+
"""
70+
71+
def foobar(self):
72+
# Increment invocation_count normally
73+
print('will halt')
74+
breakpoint()
75+
self.invocation_count += 1
76+
return self.invocation_count
77+
78+
def get_invocation_count(self):
79+
return self.invocation_count
80+
81+
def get_dynamic_value(self, key):
82+
return self._state.get(key, None)
83+
84+
85+
# Initialize Ray
86+
ray.init(
87+
runtime_env={
88+
"env_vars": {"RAY_DEBUG": "1"},
89+
}
90+
)
91+
92+
# Create a detached actor under the namespace "my_namespace"
93+
actor = StatefulActor.options(
94+
name="stateful_actor",
95+
lifetime="detached",
96+
namespace="my_namespace"
97+
).remote()
98+
99+
# breakpoint()
100+
"""
101+
# Use the abstracted way to set and get values dynamically
102+
actor.key1 = 'value1' # Abstracted assignment
103+
print(ray.get(actor.key1)) # Outputs: value1
104+
105+
actor.key2 = 'value2'
106+
print(ray.get(actor.key2)) # Outputs: value2
107+
108+
"""
109+
ray.shutdown()
110+

examples/stateful_kill_actor.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import ray
2+
# Reconnect to Ray with the same namespace
3+
ray.init()
4+
# Get the actor from the namespace "my_namespace"
5+
try:
6+
actor = ray.get_actor("stateful_actor", namespace="pymc-stateful-actor-dev")
7+
ray.kill(actor)
8+
except:
9+
pass
10+
try:
11+
actor = ray.get_actor("stateful_actor", namespace="my_namespace")
12+
ray.kill(actor)
13+
except:
14+
pass
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env python
2+
import ray
3+
# -*- coding: utf-8 -*-
4+
5+
6+
ray.init(namespace="my_namespace")
7+
# Get the actor from the namespace "my_namespace"
8+
actor = ray.get_actor("stateful_actor")
9+
remote_val = actor.foobar.remote()
10+
print(ray.get(remote_val))
11+
12+
#assert remote_val == 'bar'
13+
14+
"""
15+
# Use the abstracted way to set and get values dynamically
16+
actor.key1 = 'value1' # Abstracted assignment
17+
print(ray.get(actor.key1)) # Outputs: value1
18+
19+
actor.key2 = 'value2'
20+
print(ray.get(actor.key2)) # Outputs: value2
21+
"""
22+
23+
ray.shutdown()
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# reconnect_actor.py
2+
import ray
3+
4+
# Reconnect to Ray with the same namespace
5+
ray.init(namespace="pymc-stateful-actor-dev")
6+
7+
# Get the actor from the namespace "my_namespace"
8+
actor = ray.get_actor("stateful_actor")
9+
# Get the previous state
10+
print(ray.get(actor.get_value.remote("key1"))) # Outputs: initial_value
11+
print(ray.get(actor.get_value.remote("key2"))) # Outputs: initial_value
12+
13+
print("-----")
14+
# Set new state
15+
actor.set_value.remote("key2", "new_value")
16+
17+
# Get the new state
18+
print(ray.get(actor.get_value.remote("key2"))) # Outputs: new_value
19+
print("-----")
20+
21+
22+
### foobar
23+
r = actor.foobar.remote()
24+
print(ray.get(r))
25+
26+
r = actor.foobar.remote()
27+
print(ray.get(r))
28+
29+
30+
invocation_count = ray.get(actor.get_value.remote('invocation_count'))
31+
print(invocation_count) # Outputs: new_value
32+

0 commit comments

Comments
 (0)