Louwrens
10/29/2024, 12:37 PMStefan Krawczyk
10/29/2024, 4:32 PMStefan Krawczyk
10/29/2024, 4:55 PM# kick this off in some process
dr = driver.Builder().with_modules(...)...build() # create hamilton driver
batch = []
flush_interval = ...
last_flush = time.now()
while True:
messages = queue.get(..., timeout=...) # this waits for data from the queue
if messages:
batch += messages
interval = time.now() - last_flush
if len(batch) > ... or (batch and interval > flush_interval):
if batch:
result = dr.execute([...], inputs={"batch": batch})
# do something with result
last_flush = time.now()
batch = []Stefan Krawczyk
10/29/2024, 5:55 PMdef events(queue: ...) -> list[SomeEvent]:
while True:
# loop until event
_events = queue.get(..)
if _events:
return ...
then the driver code is a simpler loop:
# kick this off in some process
dr = driver.Builder().with_modules(...)...build() # create hamilton driver
batch = []
flush_interval = ...
last_flush = time.now()
queue = ...
while True: # or some other loop condition
results = dr.execute([...], inputs={"queue": queue}) # will only proceed when `events` would return
...Louwrens
10/30/2024, 5:37 AMevent = multiprocessing.Event() via the inputs, but the builder validator was complaining about the data type supplied not matching the function definition argument (something about one of them being a bound method). I don't quite understand how to specify the type correctly. I have a hunch I would need to setup the context correctly in the node....Stefan Krawczyk
10/30/2024, 5:53 AMtyping.Any to get around it. Otherwise open up an issue, we could very well be not comparing a type with a value correctly.Louwrens
10/31/2024, 9:09 AMevent{"myevent": multiprocessing.Event()} and defining the nodes with the dict type was sufficient to pass the validator, but ....
Traceback (most recent call last):
File "/home/louwrens/.local/share/virtualenvs/backend-c_br_Y8y/lib/python3.8/site-packages/hamilton/execution/executors.py", line 193, in get_state
self.future.result()
File "/home/louwrens/.pyenv/versions/3.8.18/lib/python3.8/concurrent/futures/_base.py", line 437, in result
return self.__get_result()
File "/home/louwrens/.pyenv/versions/3.8.18/lib/python3.8/concurrent/futures/_base.py", line 389, in __get_result
raise self._exception
File "/home/louwrens/.pyenv/versions/3.8.18/lib/python3.8/multiprocessing/queues.py", line 239, in _feed
obj = _ForkingPickler.dumps(obj)
File "/home/louwrens/.pyenv/versions/3.8.18/lib/python3.8/multiprocessing/reduction.py", line 51, in dumps
cls(buf, protocol).dump(obj)
File "/home/louwrens/.pyenv/versions/3.8.18/lib/python3.8/multiprocessing/synchronize.py", line 220, in __getstate__
context.assert_spawning(self)
File "/home/louwrens/.pyenv/versions/3.8.18/lib/python3.8/multiprocessing/context.py", line 359, in assert_spawning
raise RuntimeError(
RuntimeError: Condition objects should only be shared between processes through inheritance
I'll try to start a multiprocessing Manager to avoid passing anything in a Hamilton node entirely. (https://docs.python.org/3/library/multiprocessing.html#using-a-remote-manager)
Let me know if think of something, and/or you're interested in me opening an issue!Stefan Krawczyk
10/31/2024, 3:55 PMStefan Krawczyk
10/31/2024, 3:56 PMStefan Krawczyk
10/31/2024, 3:57 PMStefan Krawczyk
10/31/2024, 3:58 PMStefan Krawczyk
10/31/2024, 3:59 PMAvoid Passing Synchronization Primitives: Ensure that any object being passed between processes does not contain synchronization primitives. If you need synchronization between processes, consider using shared variables orto manage shared state instead.multiprocessing.Manager
Louwrens
11/04/2024, 9:35 AMLouwrens
11/04/2024, 9:45 AMnumpy.ndarray) and also (b) to pass the shape and dtype metadata of such shmem objects (via Redis set/get)...
What do you think? I was thinking that if we're going to use Redis, we might use it as a caching backend for Hamilton too... Is that something realistic? or perhaps would you have alternatives that are already available to Hamilton that might do the signaling/metadata store features we're looking for?Louwrens
11/04/2024, 9:46 AMI have seen serialization issues before with inputs etc, but nothing like this error.Do you have examples around? perhaps there is a pattern that I can follow
Louwrens
11/04/2024, 10:00 AMIs it due to the queue / event ? or?I believe the
multiprocessing.Event object needs the right process context. Is there a way get this context from within the hamilton node? or perhaps, can I create a context = multiprocessing.get_context() myself and pass it to the Hamilton dynamic executor? so that I can attach my own some_event = context.Event() to it? ...Stefan Krawczyk
11/04/2024, 4:05 PMLouwrens
11/05/2024, 9:11 AMStefan Krawczyk
11/05/2024, 4:58 PMLouwrens
11/06/2024, 4:18 PMStefan Krawczyk
11/06/2024, 5:13 PMLouwrens
11/13/2024, 8:44 AMLouwrens
11/13/2024, 8:45 AMLouwrens
11/13/2024, 8:49 AMLouwrens
11/13/2024, 8:49 AMLouwrens
11/13/2024, 8:50 AMParallelizable[]/Collect[]
⢠Analyses: within the DAG as distinct nodes
⢠Analysis repetitions: some analyses have calculation nodes that are to be run for an array of photos/modalities (a handful), via Parallelizable[]/Collect[] or
⢠Analysis repetitions: as distinct nodes, generate by @parameterize?Louwrens
11/13/2024, 8:52 AMParallelizable[]/Collect[] for nodes that in between nodes that already do Parallelizable[]/Collect[] ?
⢠Can we do async nodes within synchronous nodes perhaps?
⢠How can we do @parameterize (or similar) to generate a list of nodes that collect the desired photos from shmem, by iterating over several Enum names and/or repetition indices? (without manually writing out all the photo modalities in `dict`s)Louwrens
11/13/2024, 8:54 AMGracefulErrorAdapter for several kinds:
⢠to abort all running container processes (major fault detected)
⢠to abort a single container process (container can be rejected after early analysis already finds defects, without doing more analysis)Louwrens
11/13/2024, 8:54 AMLouwrens
11/13/2024, 8:55 AMA -> Bn (A forks into Parallelizable n elements, say containers)
Bn -> Cnm (another Parallelizable m elements, say repetitions)
Cnm -> helpers (blocking calls to photoloader or calculation, possibly an `asyncio.gather()`?
Cnm -> Dn (Collect m)
Dn -> E (Collect n)Louwrens
11/13/2024, 8:55 AMLouwrens
11/13/2024, 8:59 AMStefan Krawczyk
11/13/2024, 4:21 PMStefan Krawczyk
11/13/2024, 4:28 PMParallelizable[]/Collect[] for nodes that in between nodes that already do Parallelizable[]/Collect[] ?
In the same DAG, not right now. We have not enabled that. But you could do Hamilton within Hamilton. E.g. a node that internally that executes its own Hamilton driver.
> Can we do async nodes within synchronous nodes perhaps?
Yes. Hamilton has an async driver, though it doesnât support everything due to async.
You could also have Hamilton within Hamilton, e.g. a node that creates a driver + asyncio.run
> How can we do @parameterize (or similar) to generate a list of nodes that collect the desired photos from shmem, by iterating over several Enum names and/or repetition indices? (without manually writing out all the photo modalities in `dict`s)
So to handle more dynamism itâs either parallelizable + collect, or resolving values at DAG start time (via @resolve_with_config), or you do it before creating the hamilton DAG and provide it as input (e.g. outerloop that delegates to a hamilton DAG, or do Hamilton within Hamilton).
Let me know if that helps clarify things. My suggestion here is letâs work bottom up, design Hamilton DAGs for the specific components as you list out. Then we either manually orchestrate, or add Hamilton on top, or use something like Burr.Louwrens
12/05/2024, 8:27 AM