Results 51 comments of Li Xinqi

这个问题看起来非常尴尬

该多进程方案仍然无法处理非均匀切割下大量comm_net op所带来的编译时间过长问题。

相关代码早已合并到Master

和后江,建浩开会结论: 1. python接口不叫flow.tmp_compute_stream_type(),而是直接对齐pytorch的torch.cuda.Stream和torch.cuda.stream。 2. 一条Stream一个线程。

将flow.tmp_compute_stream重构为flow.stream(flow.Stream())。 与之前讨论的稍微有点不一样,flow.Stream并不独占某个线程,而是回环地使用固定数量的worker线程池中的一个。

> 我仍然觉得一个stream一个线程比较合适,回环地使用固定数量的worker线程池中的一个倒不如约定用户最多可以同时创建N个Stream 首先,上层用户的Python代码可能是这样的: ```python class Foo(): def __init__(self): self.stream = flow.Stream() def forward(self): with flow.stream(self.stream): ... ``` 显然self.stream被持有了,某个线程就会一直存在。这样的代码并不是低频的,尤其是库文件里,于是就会大量创造worker线程,引发各种问题。 其次,cpu stream 所在的线程需要初始化一个thread_global_id,这个目前很受限,最多只能有8个,main线程,scheduler线程和default worker线程已经占了3个。最后只剩下5个了线程允许初始化不同的thread_global_id。如果允许任意多个worker 线程,运行global op的时候肯定会崩溃的。

与后江,建浩会议结论: 1. Stream创建接口修改为:flow.Stream(worker_thread=None),若worker_thread为None,内部谁定为默认的临时线程。 2. worker_thread不能随意创建,只能通过flow.get_worker_thread(worker_thread_id)获取,而且有限额,大概是4个。 3. python生命周期不重叠的flow.Stream可以复用底层c++的Symbol。 4. 同一个线程内,不同flow.Stream对象都会共享同一个nccl stream。 这是为了解决如下几个经典断流问题: ### print(loss)断流问题。 问题描述: ```python loss = model() loss.backward() foo(loss) print(loss) ``` 因为foo函数所产生的op的实际执行排在backward op之后。所有打印loss时需要等待backward和foo对应op的完成,造成断流。 可以使用flow.Stream将如下代码重构为: ```python loss = model() loss.backward()...

应该不需要再考虑stream内顺序化机制是否要重构。 具体场景: ```python with flow.stream(flow.Stream()): Foo() with flow.stream(flow.Stream()): Bar() ``` 由于flow.Stream的复用机制,实际上Foo和Bar op会顺序执行。这应该不需要再重构,如果不复用的话会有内存暴涨问题,比如说: ```python for i in range(999999): with flow.stream(flow.Stream()): Foo() ``` for循环内的Foo每次iter都不会和上一次iter顺序化,这就完全可能造成内存暴涨。 另外,我们不应该鼓励flow.stream(flow.Stream())这种写法,而应该是类似python一样持有flow.Stream的做法。 ```python def MyModule(nn.Module): def __init__(self): ... self.stream...

针对 https://github.com/Oneflow-Inc/oneflow/pull/8866#discussion_r955574611 这个问题。与后江开会讨论结果: 1. python层的flow.Stream名不副实。它其实在导出flow.StreamSet概念,即这是一个跨StreamType/DeviceType的概念,与一般用户理解的stream从属于device这一常识相去甚远。 2. stream这个词在用户看来会联想到他需要主动做相关的操作,比如synchronize,但其实oneflow内建支持了同步,不需要用户额外做工作。 3. 如果oneflow后续对齐了oneflow.cuda.Stream,这会给用户带来更多的困惑:oneflow.Stream和oneflow.cuda.Stream有什么差别。 4. 应该把flow.stream重命名成flow.pipeline,而把flow.Stream重命名为flow.Pipeline,去掉flow.worker_thread,让flow.Pipeline接收worker_thread_id做参数。 5. 将c++层的StreamSet重命名成Pipeline,然后导出到python层。 6. flow.Pipeline和flow.device是同一层级的概念。 7. PipeLine,Device,StreamType这三者唯一确定一个vm::Stream对象。

> > 针对 [#8866 (comment)](https://github.com/Oneflow-Inc/oneflow/pull/8866#discussion_r955574611) 这个问题。与后江开会讨论结果: > > > > 1. python层的flow.Stream名不副实。它其实在导出flow.StreamSet概念,即这是一个跨StreamType/DeviceType的概念,与一般用户理解的stream从属于device这一常识相去甚远。 > > 2. PipeLine,Device,StreamType这三者唯一确定一个vm::Stream对象。 > > 好像和通常理解的 PipeLine (流水线) 也关联不大,更接近 c++ std::thread 的抽象,flow.Thread? > > _Thread,Device,StreamType这三者唯一确定一个vm::Stream对象_ _Thread,Device,StreamType这三者之下应该允许存在多个Stream对象。