帖子

目前显示的是 五月, 2017的博文

tensorflow resource notes

在单机版中,创建session的时候会创建devices,创建device的时候会为每个device创建一个ResourceMgr。每个ResourceMgr可以有多个container。所以,在单机版中,session被销毁后它所对应的ResourceMgr里的那些resource也会被销毁。但是分布式版中就不是如此了。

ResourceMgr有这样一个成员:

std::unordered_map<string, Container*> containers_;

container name一般是job name。每个Container里面会放很多从ResourceBase继承来的resource。

  typedef std::pair<uint64, string> ResourceKey;
  typedef std::unordered_map<ResourceKey, ResourceBase*> Container;

单机版无GPU的情况下,默认的device name是"/job:localhost/replica:0/task:0/cpu:0"。其中,job name就是localhost。

单机版的TF会运行每个step的时候,在DirectSession::RunState的构造函数中创建一个per-step的container(ScopedStepContainer),用来存放per-step resources。

ResourceKey里的那个string是resource name,一般是node name。而那个uint64是那个ResourceBase的子类的type的hash_code(type_index.hash_code())。所以不同类型的Resource可以重名。所以,对于某个特定的session来说,它是通过(device name, resource type, container name, resource name) 这样的四元组来定位到一个resource。

DT_RESOURCE是一种新的tensor类型,大约是在去年10月份的时候,0.12版加入的。它所对应的数据类型是ResourceHandle protobuf。该对象的创建以及访问被封装在Res…

offline job resource management的问题

假设我有一些分布式的、离线的计算任务需要运行。我有100台机器。每个任务有固定的资源需求。比如任务A需要30台,2个小时。任务B需要40台,3个小时。这些任务类型是固定的,但是任务数量以及什么时候被提交上来是未知的。此时对于资源管理器(resource manager)来说,就有了资源利用率和调度公平性之间的权衡考虑。

举个例子。假设我现在只有35台空闲机器,此时任务B先被提交上来,它需要40台机器。我不能满足它。接着,任务A被提交上来,它只需要30台机器,我可以满足它。那么要让任务A先于任务B开始运行吗?如果不允许,那么就会浪费很多机器资源。这时候平台部门就会遭遇质疑:为什么整个cluster有1/3都是闲着,却有让大量的job在排队?
如果允许,那么就会造成小任务优先、大任务饿死。同样会遭人质疑。就像餐馆里如果某座来的早却菜上的晚,那么服务员就得做好挨骂的准备。

There is no perfect rules。但对于大多数公司来说,机器空闲率都是重要的考核指标,公平性这东西太过于抽象,没法考核。所以对于平台部门,一般都会为了提高机器使用率而牺牲公平性。我觉得这也是KPI机制的弊端之一。

如果你什么都不想,只是让Hadoop的yarn来调度资源,每个app自己去找yarn的resource manager来申请资源。那么,yarn其实不知道app把机器申请去了之后有没有实际在用,所以不会在机器使用率上达到一个优化的调度。对于APP来说,它本来只需要40台机器3个小时,但是为了等到这40台机器可能要等10个小时,而这10个小时它可能一直在占用大量的机器。

只要资源很紧张,再接下来,几乎一定会遇到job优先级的问题。有了优先级,一般就会做oversell 以及 可抢占式调度。这样才能让高优先级的任务真正“优先”起来。否则只能人为的划分多个cluster,从而又降低了机器使用率。



tensorflow中实现分布式的Barrier挺让人头疼

分布式training中,经常需要让所有的节点在某一个点同步一下。比如,

只有id=0的worker进行完所有初始化操作后,其它的worker才能开始运行training只有所有的worker都train完后,才能开始dump model 那么怎么实现这样的同步功能呢?最naive的做法是,声明一个int类型、形状为scalar 的 tensorflow variable。这个variable的初始值为0,每个worker到达sync point的时候,就把这个tensor的值加1。然后不停的sleep && get value。如下面代码所示: 声明
finished = tf.get_variable("worker_finished", [],tf.int32,tf.zeros_initializer(tf.int32),trainable=False) with finished.graph.colocate_with(finished): finish_op = finished.assign_add(1,use_locking=True) 使用:
worker_finished = sess.run(finish_op) print('%d worker finished' % worker_finished) if is_chief: try: while worker_finished < worker_count: time.sleep(3) worker_finished = raw_sess.run(finished) print('%d worker finished' % worker_finished) except Exception as ex: print('exit with error:%s' % str(ex)) return
但是这样有个缺点:所有的variable默认都会被写入到checkpoint中,这个也不例外。所以,当下次从checkpoint中再载入时,就乱套了。能不能不让saver保存这个variable? 可…

I hate Condition Variables

我讨厌条件变量。条件变量应当尽可能避免被使用。一旦使用了条件变量,就意味着你需要call它的wait方法。这就像Sleep一样,会让当前线程陷入睡眠,白白浪费掉。而且使得当前线程不易被cancel。在唤醒的时候,如果实现不当,常常会“惊群”或者丢失更新(lost signal)。条件变量的wait是wait on single object,这样是不好的。不能多路复用。要尽可能的wait on multiple object。很多程序之所以不能干净的退出就是因为滥用了条件变量,tensorflow就是一个例子。

所以,更好的做法是把条件变量被唤醒后要做的事情包装成线程池里的一个task, 由调用notify方法的线程把这个task扔到线程池里。这样cancel起来其实也很容易,只要给这个task设置一个标志位,在把这个task扔进线程池之前和开始执行之前各检测一次就好了。最后,程序会变成被一大串async callback串起来。虽然先后逻辑看起来不再那么直观,但是画个图、写写文档也就好了。

我一般只有在main函数中才可能会使用条件变量。目的是等待child threads结束。


三年,三位朋友离世

2015年,ZJ,我学长,以及前同事。
2016年,夏兄。前同事。
2017年,唐兄。川藏线上偶遇的朋友。
面对着这一个个离去的朋友,我的心情真的有点沉重。他们都是30岁上下,走的挺突然。如佛经里反复所说,“人生无常”。可又有多少人能接受这四个字呢?下面是我对他们的一点怀念。

先说说唐。我在川藏线上被他"捡"过。那是2015年的春天,我刚刚失业,独自一人在川西游玩。我在海螺沟一个亭子里遇见Z。我背着60L的大包,气喘吁吁的在休息。他也累了,在我旁边坐下。我们就聊了起来。得知他是重庆人。刚买了车,带着老婆,和一对朋友夫妇,准备绕着川西开一圈。他看我独自一个人,于是就很热情的要带我一起走。其实他那个车有点小,坐4个人刚好,坐5个人就有些挤。但盛情难却。于是我就厚着脸皮当了几天灯泡。后来的旅途确实很开心。我们在公路上眺望红石滩,在折多山顶玩雪,在人迹罕至的寺庙里逗孔雀,望着阳光下的金顶出神,路上饿了就在车后排嚼风干的牦牛肉干。可惜我们路线不一致,我很坚定的想要去色达,而他们的车地盘低去不了那种路,他们要继续他们的川西环线。快要分开的那半天,我们都有些依依不舍。他开车送我到分岔的地方,看我上了去色达的车,才放心的带朋友们离去。分开时我要给他些油钱,他死活不肯收。说好以后在重庆或者北京再聚。多好的一条汉子啊。他媳妇很漂亮对他也很好。当时他们还没孩子,还在为买房攒钱。接下来这2年可谓是家庭美满,生活一帆风顺。可惜转折来的太突然。

然后说夏。我的职业生涯中,与夏可谓交集颇多。我和他曾是两任同事。后来又蒙他的推荐去投奔了黄。因为他说黄这人对下属很好,值得跟随。黄曾是夏在S公司的领导。几年后,他也去跟了黄,重新成为他的下属,负责一片新业务。夏虽背景一般,非名校毕业,但是对技术一直抱有热忱,喜欢钻研,工作也非常努力。加起班来那真是没日没夜。他曾在几家游戏公司带过几个游戏项目,担任程序的头。这样的工作有多累,你应该能猜到。所以他后来再去别的公司,我估计他一定有些有劲使不上的感觉。他是真心的喜欢GNU/Linux、图形算法这些东西,而不是只把它们当作谋生的工具。他有过数次创业的经历,也曾屡屡想邀我加入。记得有一次,我们在某个酒吧谈及创业选人的那点事儿,他说,他会看这人是否对父母孝顺,不孝的人不值得信任。我当时很惊讶,这样的观点我还是第一次听说。但是随后想想也觉得自然。…