博文

目前显示的是 2017的博文

想换个新路由器

我现在的路由器是netgear r6300v2,真的是太赞了。网上口碑甚好。这是我用的第一款基于ARM的路由器。但是我还是想换一个更好一点的。

于是在思索两种方案,一个是继续走ARM的路买一个r6300的升级版,另一个是选一个mini-itx无风扇的系统装Linux做软路由。

然后我先调查了一下ARM的情况。SoC基本被高通和Broadcom垄断了。

高通家的可以分为两类:IPQ4018/IPQ4019/IPQ4028。Cortex A7,主频717 MHz,比如Google Wifi,netgear Orbi就采用了这系列。
 另外就是IPQ8062/IPQ8064/IPQ8065等等。这些用的是Krait处理器,主频和A15差不多。 代表作Netgear R7800。

另外就是Broadcom Northstar系列:BCM4707/BCM4708/BCM4709/...,比如我的6300v2用的就是BCM4708A0。这些基本都是基于Cortex A9的。基于Cortex A53的设备我只找到两个:ASUS RT-AC86U,它用的是BCM4906,以及LINKSYS EA9300,基于Broadcom BCM4908。前者售价大约1000,后者2000。我还看不出来为什么后面这个这么贵。

目前看起来,ASUS RT-AC86U真是性价首选。但是netgear的设备对open source支持的更好些。

嗯,其实我未必需要wifi啊。哪怕给我一个纯路由,我在后面再接别的也行啊。不知道是不是选择可以更多一些。

再说x86这边。大部分低功耗的主板都只有一个网口,所以不适合做路由。高功耗的主板需要风扇,对我来说太吵了。我找来找去,非山寨的,就只有超微在做这样的产品。目前看中了E200-9B。E100-9AP和E200-9AP看着也不错但是我不知道去哪买。总之这些都很贵,至少2000元以上。但是优点是我可以用最新的Linux发行版和内核,可定制程度高,而且不用交叉编译不用移植代码省人工啊!就是我不知道噪音情况怎样。

web证书现在需要 Subject Alternative Name了

我刚发现我之前自己给自己签发的web server的证书在chrome下都失效。 chrome提示说:
 security certificate is from [missing_subjectAltName]. This may be caused by a misconfiguration or an attacker intercepting your connection.

据说这是chrome 58开始的新特性。我在找怎么修改openssl的命令以添加这个新属性进去。找了一半天没找到,网上的文档似乎都是得写一个配置文件才行,而我又比较懒。

我现在用的命令是:

openssl genrsa -out server.key 2048

openssl req -new -key server.key -out server.csr

openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt -extensions v3_req

如果你知道新的正确的,请告诉我




2017-07-03

上个月给手机升级了Android O,太慢太卡了,于是今天又刷回Android 7.1。顺便root了一下。我是通过自己编译adbd然后放入boot.img来root,但是很奇怪,似乎我用cpio手动打包的initrd.img 总是有问题,不能boot。只能通过在asop的源代码中make bootimg来生成boot.img才行。嗯……一定是我漏了什么。


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、图形算法这些东西,而不是只把它们当作谋生的工具。他有过数次创业的经历,也曾屡屡想邀我加入。记得有一次,我们在某个酒吧谈及创业选人的那点事儿,他说,他会看这人是否对父母孝顺,不孝的人不值得信任。我当时很惊讶,这样的观点我还是第一次听说。但是随后想想也觉得自然。…

tensorflow python script examples

图片
Tensorflow中每个节点的每个输出被称为Tensor。 (Represents one of the outputs of an Operation.)
python中的tf.Tensor只是一个symbolic handle。
下面是tensorflow的一个简单的example
# Build a dataflow graph. c = tf.constant([[1.0, 2.0], [3.0, 4.0]]) d = tf.constant([[1.0, 1.0], [0.0, 1.0]]) e = tf.matmul(c, d) # Construct a `Session` to execute the graph. sess = tf.Session() # Execute the graph and store the value that `e` represents in `result`. result = sess.run(e) #clean up sess.close() 输出:
[[ 1. 3.]
[ 3. 7.]]
上面这段代码中,c,d,e,都是tf.Tensor类型,result是numpy.ndarray类型。矩阵运算是在sess.run()里面执行的。一个graph,就像是数据库里的预编译好的语句(prepared statement),而sess.run()就是执行这个statement。tf.matmul,tf.constant这些都是operation。
就像我们在执行SQL的时候可以塞参数进去一样,执行tensorflow的graph时也是如此。Tensorflow中把这个机制称为Feeding。
Feeding 下面是一个带参数的例子:
import tensorflow as tf # Build a dataflow graph. c = tf.constant([[1.0, 2.0], [3.0, 4.0]]) d = tf.constant([[1.0, 1.0], [0.0, 1.0]]) e = tf.matmul(c, d) # Construct a `Session` to execute the graph. sess = tf.Session() # Execute the…

用java生tensorflow的tfrecord文件

如果你的training data在hadoop上,那么java恐怕是你做数据预处理的最佳语言。为了在Hadoop上生TFRecord文件,你需要三样东西:

protoc,版本需要和hadoop上的protobuf版本保持一致tensorflow的源代码下面的TFRecordFileWriter
首先运行下面的命令生成protobuf messages的java文件 protoc --proto_path=C:\tensorflow --java_out=. C:\tensorflow\tensorflow\core\example\example.proto
然后把下面这个class添加到你的项目中 package com.bing.imagetool; import java.io.BufferedOutputStream; import java.io.Closeable; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import org.tensorflow.example.BytesList; import org.tensorflow.example.Feature; import org.tensorflow.example.FloatList; import org.tensorflow.example.Int64List; import com.google.protobuf.ByteString; public class TFRecordFileWriter implements Closeable { /** * Implements CRC32-C as defined in: "Optimization of Cyclic Redundancy-CHeck Codes with 24 and 32 * Parity Bits", IEEE Transactions on Communications 41(6): 883-892 (1993). * * The implementation of this class has been sourced from the Appe…

盼了多年的“医药分离”终于来了,玩这么多猫腻就为了给医保省钱

现在去医院看病,医院会对药物收15%的加价。比如进价100,卖给病人115。这其中的15块钱就留作利润供医院运转。这样的模式让医生、病人、医保都怨声载道。医院为了利润,就拼命开药,过度医疗。病人每次一去医院就是一张大处方,背一书包的药回来。医保则是想不通,它为什么要出这15%的钱。医生觉得自己很郁闷,做一台手术才几百块钱的手术费,价值得不到体现,还不如跟医药代表合作,多开点吃不死人也没什么疗效的中成药。这其中的弊端谁都知道。于是医药分离提了至少10多年了,国家各种媒体从我上中学提到现在。

那现在的结局是怎样呢?简单点解释是这样:医保说,病人啊,你以后每次看病,来我这领一张价值100元的优惠券,然后凭此券去医院开药,可享受9折优惠,每张券限使用一次。然后医院拿着这个券去找医保报销,把它损失的药费要回来。这个优惠券就叫医事服务费。你觉得这样好吗?

核心问题在于:医保每年给每个病人所能支出的费用是固定的。医保就是个保险,国家基本不出钱,只抽管理费。每个参保人平均来算,交上去的肯定比拿回来的多。差值就是管理费。支出总额固定的情况下,一部分变成了“优惠券”,那么病人能享受到的药品、耗材就必须减少。具体来说,比如挂号费42,医保报销40,个人出2元。那么这些钱,其实就相当于股票基金的赎回费率。你去医院挂号,就相当于是在申请赎回基金,你在申请把你之前存进去的钱拿一部分回来。看病掏的挂号费,赎基金掏的是基金手续费。你不会因为挂号费从5块钱变成42,14变成100,就能因此得到更好的医疗服务。做梦呢。该3分钟打发你还是3分钟打发你。举个例子,北医三院现在是5块钱的挂号费,朝阳医院是42元,你能感受到朝阳医院的医疗服务比北医三院好?或者朝阳医院的医疗服务比它提价之前好?医院虽然诊疗费的收入提高了,但是药费利润没了啊。医保办是纯赚。参保人是亏。

医保办要求再次降低药占比,今年要降低到30%。举个例子,有个老人高血压,以前花5块钱挂号费,就开800的药回来。现在不行了。他要花200块钱挂号费才能开100块钱的药回来。挂号费改革后一次最贵100。他花了100块钱挂最贵的号,只能开50块钱的药。根本不够一周的药费。于是医生只能说,那这样,我给你测个血压,这一项再收你300的服务费,这样就可以开药了。测个血压为什么要300?国家逼的啊。媒体吹了这么久的风说要提高医师服务费,就是因为这个。



bug经历: 物理内存耗尽,但是不知道是哪个进程干的

最近我发现一个很奇怪的事情,tensorflow的windows版有一个很奇怪的内存泄露的bug。我的电脑有16GB内存。但是tensorflow一旦跑起来,机器很快就会内存不足,然后page file频繁的换入换出。但是tensorflow这个进程本身呢,并没有内存泄露。它的堆并没有增长。我用windbg仔细检查过它的所有内存,堆的,栈的,各种类型的,都没有增长。嗯,电脑突然没了10几GB的物理内存,但是tensorflow只占了几百M。我把这个电脑里所有进程的所有内存使用量加起来,也远远不够10GB。我可以肯定是tensorflow干的。因为我一旦把tensorflow的进程杀死,丢失的内存立马就回来了。一旦重新启动tensorflow,内存又逐渐的没了。

最终,我发现,是我的一个美国同事,checkin了一个很糟糕的修改。他给tensorflow的windows file system的实现引入了两个很严重的bug。
他原始的pull request是:https://github.com/tensorflow/tensorflow/pull/5020
第一个被发现的bug是:https://github.com/tensorflow/tensorflow/pull/6805
第二个就是我刚才说的,内存泄露。

sysinternals里有两个工具可以查看内存去哪了。一个是vmmap。是查看单个进程的。另一个是RAMMAP,可以查看物理内存具体被map到哪去了。最终我发现,是以memory mapped file的方式消耗掉了。而那个file就是tensorflow运行时正在读的那个file。

揭秘的时刻来了。原来是它打开文件的时候加了FILE_FLAG_RANDOM_ACCESS参数。然后windows内核在看到这个参数后,就会把所有已读入的内容,一直lock在内存里。参见https://support.microsoft.com/en-us/help/2549369 。 不加这个参数,文件系统也会做cache,但是这部分内存的类型是Standby。加了这个参数,这部分内存就变成了Active状态。

最后,我把这个报告了给tensorflow的github仓库,看看他们准备怎么办。https://github.com/tensorflow/tensorflo…

痛苦的DLL

有时候你必须得用到DLL。

比如,假如你想在python或者java中调用C/C++的code。那么这些native code必须得编译成一个DLL。
再比如,VC对单个exe/lib/pdb的文件大小有2GB的限制,这些限制很容易在debug版中hit到。

最大的麻烦在于将一个DLL拆成多个DLL。windows下要求DLL之间不能有循环依赖。举个例子,假如你实现了一个vfs.dll。这个dlll声明了一个IFileSystem的interface,和一个FileSystemFactory的Singleton。然后在其它的dll中有IFileSystem具体实现。比如hdfs.dll,httpfs.dll,nfs.dll…… 与Linux不同的是,Windows下编译hdfs.dll等这些dll的时候,它所用到的所有符号必须要能找到具体的实现。也就是说,这些dll必须要链接到vfs.dll。vfs.dll必须把所有实现时所需要用到的函数、类、全局变量都导出。举个例子,假设vfs.dll和其它的dll都用到了zlib。那么要么zlib被全部打包进vfs.dll,那么zlib也必须编译成一个dll。否则,如果这些dll都静态链接到zlib,那么zlib中的全局变量就会有多份拷贝。

不是所有的符号都可以导出。一个典型的麻烦例子就是STL里的容器。How to export an instantiation of a Standard Template Library (STL) class and a class that contains a data member that is an STL object . 简单点说:std::string以及STL里除了std::vector以外的所有容器都是不可导出的。所以,一般来讲,DLL的interface里最好不要有STL的数据结构。这个限制挺让人恼火的。

追根溯源,DLL并没有weak symbol这样的东西。于是template class里的静态变量就会在同一个进程里有多份实例,每个dll里都可有一个。一个典型的例子就是std::string::npos。唯一的解决办法就是显式的对模板类实例化。但是对于STL来说,这个过于复杂,不大可能做到。




纯C++的tensorflow trainer

今天写了一个纯C++的tensorflow trainer。大体来讲,main函数里要干这么几件事情:

创建grpc serverload MetaGraph创建session,执行init OP从meta graph得到queue def,创建并运行queue执行training loopsave model 这里的meta graph是用python生成的。主要是因为C++的API还没有把auto gradient做完善。不仅如此,目前用C++构造graph的代码远远比python复杂,没有任何优势。
training loop的跳出方式有两种。 一种是等待抛出out of range错误。这个在C++中可以通过检查run方法的返回值,在python中可以catch异常。 另一种是显式的设置step个数。这种一般需要预先知道有多少training samples。sample_count * iteration_count/mini_batch_size就可以得到max step。这种通常用于需要按iteration调节learning rate的场景。
唔,折腾一半天有啥实际好处呢?我拿alexnet在没有GPU的机器上试了下,performance并没有什么差别。主要是因为对于这样的复杂的网络结构,python层所占的cost很小。我准备明天再在有GPU的机器上试一试看。

mysql jdbc client端也加了一个maxAllowedPacket参数

不知道这是从哪个版本开始的,mysql jdbc client端也加了一个maxAllowedPacket参数。
所以我一再的修改server上的 max_allowed_packet 设置都没有用。

mysql> show global variables like '%packet%';
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| max_allowed_packet       | 16777216   |
| slave_max_allowed_packet | 1073741824 |
+--------------------------+------------+
2 rows in set (0.00 sec)


java里还是报告

Caused by: com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for query is too large (100,152 > 65,535). You can change this value on the server by setting the 'max_allowed_packet' variable.
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:100)
at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1983)
at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1936)
at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java:1422)

FUCK!

解决办法就是client端也得改

tensorflow alexnet performance test

放一些最近做的测试

测试1:
tutorials\image\alexnet\alexnet_benchmark.py:
网络结构:
conv1   [128, 56, 56, 64]
pool1   [128, 27, 27, 64]
conv2   [128, 27, 27, 192]
pool2   [128, 13, 13, 192]
conv3   [128, 13, 13, 384]
conv4   [128, 13, 13, 256]
conv5   [128, 13, 13, 256]
pool5   [128, 6, 6, 256]

batch size=128

E5 1630-v3 4核
 step 0, duration = 1.412
 Forward across 10 steps, 1.334 +/- 0.039 sec / batch
 step 0, duration = 4.181
 Forward-backward across 10 steps, 4.175 +/- 0.170 sec / batch

GTX 970:
 step 0, duration = 0.046
 Forward across 1 steps, 0.046 +/- 0.000 sec / batch
 step 0, duration = 0.137
 Forward-backward across 1 steps, 0.137 +/- 0.000 sec / batch

K20m:
  Forward across 100 steps, 0.093 +/- 0.001 sec / batch
  Forward-backward across 100 steps, 0.253 +/- 0.001 sec / batch


测试2,model/slim下完整的training:
alexnet v2 batch size=128
K20m: 0.35s
gtx 970: 0.2s
E5 1630-v3: 27s

inception v2: batch size=32
K20m: 0.83s
gtx 970: 0.52s


还有些我没贴出来。我觉得会不会是哪里搞错了。。。。太诡异 首先,不同CPU的性能差不多。尤其是20核的居然和普通家用的4核差不多。 其次…

docker 1.13默认会在iptables里drop forward包

我发现我在升级docker 1.13后,我的openvpn就不能用了。经水木Dieken指点,发现这是docker更改了默认行为
https://github.com/docker/docker/pull/28257

解决办法有好几种:

1. 根据自己的情况添加白名单
sudo iptables -I FORWARD -i tun+ -o eth0 -s 192.168.0.0/16 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/16 -o eth0  -j MASQUERADE  (这条原本就需要)

2. 把默认规则改回ACCEPT
sudo iptables -P FORWARD ACCEPT

3. 修改sysctl的默认设置
只要sysctl里的ip foward不是docker打开的,docker就不会把默认的drop规则添加进去。

tensorflow distributed runtime初窥

图片
一个Tensorflow的Cluster包含多个Job,一个Job包含多个task,每一个task都是一个进程。
Job相当于Server Role。一般是分成"ps"和"worker"两种。
每个task会有1个或多个device, 如"cpu:0"、"gpu:0"。在创建graph的时候,可以指定node被place到哪个device上。tensor在device和device之间的传输由tensorflow distributed runtime自动完成。这就是tensorflow的分布式的核心设计思想。

tensorflow的分布式设计相比于它的前身DistBelief有什么改变和优势呢?

首先,DistBelief里只有两种角色:parameter server和worker。而tensorflow在摒弃parameter server这个概念,它希望把parameter server做的更generic一些。它认为,parameter server也是既需要做运算,也需要做KV存储,所以它和计算梯度的worker并没有本质的不同,只是它比较“被动”。Google希望,当想尝试一个新的优化算法时,如FTRL、Adam,不必去改parameter server的code。

于是在tensorflow中,就变成了:有一个进程负责分配任务和存储到其它节点,而其它节点负责执行收到的任务。那个分配任务的就是master节点。其它的slave节点就是传统意义上的parameter server。被分配的任务是Partial graph execution。存储是variable。整个计算流程由master节点来drive。再往上层来讲,假如你采用了training data partition,那么,每个data partition都应对应一个master节点。每个master节点都对应一个tensorflow session。每个slave节点可以同时支撑来自多个master的多个session。

Tensorflow中的session有两个实现,GrpcSession和DirectSession。前者是给分布式用的,后者是给单机用的。


一个GrpcSession的执行环境中包含一个m…

Windows下用copy命令合并文件的时候小心末尾的0x1A

把几个文本文件合并成同一个,在Linux下很简单,
cat src*.txt > dest.txt
就可以了。

在Windows下可以用copy命令:

copy src*.txt dest.txt

但是这样复制出来的文件,dest.txt的末尾会多一个0x1A。这个是Windows系统中特有的eof-of-file marker。这个"Feature"害得我debug了好久。

解决办法:
在源文件的后面加/a
在目的文件的后面加/b
同时,如果是在写脚本,别忘了在命令的最后加一个/y。

例子:

copy tmpdir\part* /a out.txt /b /y

神经网络语言模型

什么是统计语言模型?

"A language model is a function that puts a probability measure over strings drawn from some vocabulary" -- 《Introduction to Information Retrieval》

在实际使用中,一般都是n-gram模型。即,根据前n-1个词判断第n个词的出现概率。由于训练集中的样本(strings)是变长的,所以需要在原始的词表中加入两个特殊的token: START 和 STOP。前者用于表示序列的开始,后者用于表示结束。

下面举个tri-gram的例子。对tri-gram来说:

$$ p(x_1,x_2, ... , x_n) = \prod_{i=1}^np(x_i|x_{i-2},x_{i-1})$$

比如对the dog barks这句话来说,
p(the dog barks STOP) = p(the | START, START) * p(dog| START, the) * p(barks| the, dog) * p(STOP | dog, barks)

这里的概率函数p,一般是通过统计或者机器学习的方式得到的。我个人的理解是:统计语言模型并不是为了对人类的某种语言建立一个通用的模型。因为同一个词在不同的文档集中出现的频率差别很大。
其次,样本中没有出现的,不代表它的概率就是0。平滑化,即为这些未出现过的strings赋予一个非0 的概率,在传统的以counting为主的语言模型中扮演着至关重要的角色。

Distributed representation 是20世纪以Hinton 为代表的Connectionism的一个老旧概念。所有的神经网络模型,都可以认为是input的一种Distributed representation。所以我觉得可以先不去考虑这两个词的意思。常与之混淆的是Distributional representation,这个通常指的是空间向量模型(VSM)。

关于TCP可靠性的一点思考,借此浅谈应用层协议设计

本文主要讨论如何设计一个可靠的RPC协议。TCP是可靠的传输协议,不会丢包,不会乱序,这是课本上讲述了无数遍的道理。基于TCP的传输理论上来说都是可靠的,但是实际这也得看场景。当我做网络游戏的时候也是一直把它当一个可靠的传输协议来用,从没考虑过TCP丢包的问题。直到当我面临像网络存储、机器学习这样领域时,我发现TCP变得“不可靠”了。

具体来说:
发送方能不能知道已发送的数据对方是不是都收到了?或者,收到了多少?答:不能如果怀疑对方没收到,有没有办法可以确认对方没有收到? 答:不能我想发送的是“123”,对方收到的会不会是“1223”? 答:是的,会这样,而且无法避免。 第一个问题看起来很傻,众所周知TCP有ACK啊,ACK就是用来对方通知接收到了多少个字节的。可是,实际情况是,ACK是操作系统的事儿,它收到ACK后并不会通知用户态的程序。发送的流程是这样的: 应用程序把待发送的数据交给操作系统操作系统把数据接收到自己的buffer里,接收完成后通知应用程序发送完成操作系统进行实际的发送操作操作系统收到对方的ACK 问题来了,假如在执行完第二步之后,网络出现了暂时性故障,TCP连接断了,你该怎么办?如果是网络游戏,这很简单,把用户踢下线,让他重新登录去,活该他网不好。但是如果比较严肃的场合,你当然希望能支持TCP重连。那么问题就来了,应用程序并不知道哪些数据发丢了。
以Windows I/O completion ports举个例子。一般的网络库实现是这样的:在调用WSASend之前,malloc一个WSABuffer,把待发送数据填进去。等到收到操作系统的发送成功的通知后,把buffer释放掉(或者转给下一个Send用)。在这样的设计下,就意味着一旦遇上网络故障,丢失的数据就再也找不回来了。你可以reconnect,但是你没办法resend,因为buffer已经被释放掉了。所以这种管理buffer的方式是一个很失败的设计,释放buffer应当是在收到response之后。
Solution:不要依赖于操作系统的发送成功通知,也不要依赖于TCP的ACK,如果你希望保证对方能收到,那就在应用层设计一个答复消息。再或者说,one-way RPC都是不可靠的,无论传输层是TCP还是UDP,都有可能会丢。
第二个问题,是设计应用层协议的人很需要考虑的,简单来说,“成功一定是成…