I have a tiny Ray pipeline like this:
import ray import numpy as np import time @ray.remote class PersonDetector: def __init__(self) -> None: self.model = self._init_model() def _init_model(self): s = np.random.random([100, 4]) return s def infer(self, img): b = self.model[0:np.random.randint(100), :] # random batch boxes print(b.shape) time.sleep(4) return b @ray.remote class KptsDetector: def __init__(self) -> None: self.model = self._init_model() def _init_model(self): s = np.random.random([100, 17]) return s def infer(self, img, boxes): sh1 = boxes.shape[0] kpts = self.model[0: sh1, :] time.sleep(2) return kpts @ray.remote class HandDetector: def __init__(self) -> None: self.model = self._init_model() def _init_model(self): s = np.random.random([100, 4]) return s def infer(self, img): b = self.model[0:np.random.randint(100), :] # random batch boxes data = {} data['hands'] = b time.sleep(3) return data @ray.remote def gather_all(hands, kpts): t0 = time.time() if isinstance(hands, dict): print(f'in hands info: {hands.keys()}') hands = hands['hands'] if hands.shape[0] > kpts.shape[0]: out = hands.copy() out[:kpts.shape[0], :] += kpts[..., :4] else: out = kpts.copy()[..., :4] out[:hands.shape[0], :] += hands print(f'[gather time] {time.time() - t0}') return out # how to written DAG in classes? P = PersonDetector.remote() K = KptsDetector.remote() H = HandDetector.remote() t0 = time.time() img = [] boxes = P.infer.remote(img) hands = H.infer.remote(img) kpts = K.infer.remote(img, boxes) # out = gather.remote(hands, kpts) out = gather_all.remote(hands, kpts) t1 = time.time() print(t1 - t0) out = ray.get(out) t2 = time.time() print(t2 - t0) print(t2 - t1) print(out.shape)
I using time.sleep()
for fake time consuming. As you can see, the HandDetector should running in a sub process, so the whole time should be 6s.
But I got (you can have a try on your computer):
6.45377516746521 6.4489240646362305
Why there are 0.4s time more?
Advertisement
Answer
It looks like you posted the same question to the Ray GitHub (link to comment). I am copying the answer here so other StackOverflow users can benefit.
@robertnishihara: You are recreating the actors every time you call do_it, and there is some overhead to creating actors (it starts a new Python process).
If you rewrite it as follows, the overhead drops.
import ray import numpy as np import time ray.init() @ray.remote class PersonDetector: def __init__(self) -> None: self.model = self._init_model() def _init_model(self): s = np.random.random([100, 4]) return s def infer(self, img): b = self.model[0:np.random.randint(100), :] # random batch boxes print(b.shape) time.sleep(4) return b @ray.remote class KptsDetector: def __init__(self) -> None: self.model = self._init_model() def _init_model(self): s = np.random.random([100, 17]) return s def infer(self, img, boxes): sh1 = boxes.shape[0] kpts = self.model[0: sh1, :] time.sleep(2) return kpts @ray.remote class HandDetector: def __init__(self) -> None: self.model = self._init_model() def _init_model(self): s = np.random.random([100, 4]) return s def infer(self, img): b = self.model[0:np.random.randint(100), :] # random batch boxes data = {} data['hands'] = b time.sleep(3) return data @ray.remote def gather_all(hands, kpts): t0 = time.time() if isinstance(hands, dict): print(f'in hands info: {hands.keys()}') hands = hands['hands'] if hands.shape[0] > kpts.shape[0]: out = hands.copy() out[:kpts.shape[0], :] += kpts[..., :4] else: out = kpts.copy()[..., :4] out[:hands.shape[0], :] += hands print(f'[gather time] {time.time() - t0}') return out def do_it(i, P, K, H): t0 = time.time() img = [] boxes = P.infer.remote(img) hands = H.infer.remote(img) kpts = K.infer.remote(img, boxes) # out = gather.remote(hands, kpts) out = gather_all.remote(hands, kpts) t1 = time.time() out_value = ray.get(out) t2 = time.time() print(f'{i}. {t2 - t1}') print(out_value.shape) if __name__ == '__main__': P = PersonDetector.remote() K = KptsDetector.remote() H = HandDetector.remote() for i in range(3): do_it(i, P, K, H)
In this case, I get the output
(PersonDetector pid=36472) (35, 4) 0. 7.073965072631836 (95, 4) (PersonDetector pid=36472) (34, 4) (gather_all pid=36421) in hands info: dict_keys(['hands']) (gather_all pid=36421) [gather time] 6.890296936035156e-05 1. 6.016530275344849 (47, 4) (PersonDetector pid=36472) (87, 4) (gather_all pid=36421) in hands info: dict_keys(['hands']) (gather_all pid=36421) [gather time] 9.608268737792969e-05 2. 6.006845235824585 (88, 4) (gather_all pid=36421) in hands info: dict_keys(['hands']) (gather_all pid=36421) [gather time] 9.870529174804688e-05