Houjiang Chen
Houjiang Chen
我仍然觉得一个stream一个线程比较合适,回环地使用固定数量的worker线程池中的一个倒不如约定用户最多可以同时创建N个Stream
> > 我仍然觉得一个stream一个线程比较合适,回环地使用固定数量的worker线程池中的一个倒不如约定用户最多可以同时创建N个Stream > > 首先,上层用户的Python代码可能是这样的: > > ```python > class Foo(): > def __init__(self): > self.stream = flow.Stream() > def forward(self): > with flow.stream(self.stream): > ... > ``` >...
现在我们Python这个Stream的作用其实和PyTorch的Pipe更贴近(https://pytorch.org/docs/stable/_modules/torch/distributed/pipeline/sync/pipe.html#Pipe ),oneflow C++ stream是更底层的东西,它就类似于流水线里的工人,可以有多个,高级的流水线还能让指令在这些stream上乱序执行。 如果我们现在导出flow.stream,那以后为了对齐pytorch,肯定也还要导出flow.cuda.stream,这两个stream就很难向用户解释清楚了。
> 这里没有理解。流水线有一种“把任务按照固定方向往后传递“的感觉。 嗯嗯,是指令乱序,指令发射出去了在流水线内部就是固定方向传递的。
我在想能不能通过修改AttrMap的数据结构来达到类似的目的,比如每个接口中都存在一个thread_local static的CachedAttrMap,每次执行到这个接口的时候CachedAttrMap都会先fake clear一下,fake clear只是把里面存有的元素都标记为invalid,后面在SetAttr的时候会判断val和invalid的val是不是相同,相同的话就把它重新标记为valid,否则就更新val的值。这样的实现相比于缓存整个AttrMap来说,代码改动会小一些,效果会在缓存大小为1到n之间(n为属性个数),因为每次可能都只需要更新少量的几个属性。
> 我感觉成本还是不低,比如SetAttr("foo", bar)。这代码内部就涉及到不少对象创建,首先"foo"需要转成std::string,还有对map的查找。 但这个可能并不是瓶颈,主要是会节约创建AttrMap和插入的开销,而且对代码改动很小。
> > 我在想能不能通过修改AttrMap的数据结构来达到类似的目的,比如每个接口中都存在一个thread_local static的CachedAttrMap,每次执行到这个接口的时候CachedAttrMap都会先fake clear一下,fake clear只是把里面存有的元素都标记为invalid,后面在SetAttr的时候会判断val和invalid的val是不是相同,相同的话就把它重新标记为valid,否则就更新val的值。这样的实现相比于缓存整个AttrMap来说,代码改动会小一些,效果会在缓存大小为1到n之间(n为属性个数),因为每次可能都只需要更新少量的几个属性。 > > 我还对这个方案有另一个顾虑。attr_map会在多个线程里传递,最好是只读的,这和cache有点冲突。 其实也不会,CachedAttrMap会拷贝一份转成AttrMap,因为内部元素是`shared_ptr`,如果在main线程里又更新了CachedAttrMap,那也是把它的元素替换成了另一个`shared_ptr`,并不影响其他线程里的元素。
如果不跳过会有什么后果吗
可以设置环境变量ONEFLOW_CONV_ALLOW_HALF_PRECISION_ACCUMULATION=0和ONEFLOW_MATMUL_ALLOW_HALF_PRECISION_ACCUMULATION=0再试试,设置之后对于conv和linear,onediff会采用更高精度的计算方式
deepcache是有损的,可能导致模糊的问题,请去掉下面这些参数关掉deepcache关掉再试。 ``` cache_interval=3, cache_layer_id=0, cache_block_id=0, ```