先罗列下我的需求,有两台机器,一台windows 7,另一台mac,现在想在这两个机器间自动同步文件。两台机器位于不同的私有子网段,也就是说,躲在两个不同的路由器后面接入公网。

因为nat的存在,使得两台机器间直接建立tcp连接成为不可能,想了几个方案:

第一,通过一台有公网ip的机器中转,两台机器同时跟这台服务器建立tcp连接,定时交换文件时间戳并相应的更新。这种方案存在巨大的弊端,我的服务器在美国,两台挨在一起的机器,传送数据居然需要绕过层层路由跨过海底光缆传送到大洋彼端然后再传回来,速度慢,占带宽,太折腾。

第二种就是udp打洞了,假设两台机器分别为A和B,中转机器为S,这样A和B都可以向S发送UDP数据包了,S可以得到NAT转换后的ip和端口号,由于UDP不是面向连接的,任何主机都可以向这个ip和端口号发送数据。理论上讲,只要S把这些信息告诉A和B,这两台机器就可以直接通信了。但是因为安全性的考虑,如果这个数据包的ip和端口号不是先前发给S的那个地址,就会被路由器丢弃。如何取得路由器的信任,是打洞最需要解决的问题。一个简单的想法是,A向B的NAT转换后的地址发送一个udp包,这样A的NAT对于B的这个地址就是敞开的了,如果B能发出具有这样地址的包,二者之间的连接就能建立起来。

今天花了一个下午编写调试相应的代码,A和B之间的数据包始终不能成功接收,后来才意识到,A向B再次发送数据包的时候,NAT路由器会重新生成不同的端口号,换了个端口向S发包测试打印地址印证了这个想法,这个端口号似乎是随机生成的。

google了下,有些路由器确实是这样实现的,这种情况下UDP打洞基本不可行。

总之,问题没那么圆满的解决,最终还是使用方案一中转,先只同步小文件吧,至少比手动拷方便些。

客观评价下NAT对互联网的影响吧,好的方面:解决了ip地址快速耗尽的问题,估计延缓了一二十年。也提高了安全性,某种程度把病毒隔离在一个个子网范围内。

另一方面,把端口号扩展为ip地址的一部分,本身就是一种很踅脚的做法,增加了软件的复杂度。一个好的设计应该简单统一,不应该让人在实现的时候感到头疼。

在已有系统上缝缝补补,用最简单的改变来适应环境,是生物的进化的基本特征。互联网在遇到问题时的解决方案似乎也在重复着大自然的脚步。

还是希望ipv6早日普及吧。

最近想买辆车,相关的东西大致都看或者了解了下,以前对机械相关的专业了解的不多,甚至有些偏见。机械是个成熟复杂的领域,积累了很多研究理论,大量的极具巧思的器件。单单是对这些相关的器件的理解,足以对大脑的思考模式产生重大影响。

举一个简单的例子,汽车在行进当中进行转弯的话,内侧和外侧的轮子的速度是不同的,这时候发动机的输出就要对不同的轮子进行适当调整,如何动态的做到?方法有很多种,最简单的方法,只用一个轮子作为驱动轮,这样其他轮子就只在地上滚动了,早期汽车用的就是这种方法,这种方法其实是在逃避问题,一个轮子驱动有很多弊端。现在的汽车都使用一种叫做差速器的简单装置,可以巧妙的处理这个问题,具体细节用文字解释起来比较麻烦,感兴趣的话可以到youtube上看相关的视频解说。

现代的发动机是个复杂的装置,通过厂商鼓吹的一些技术特点,比如涡轮增压,可变气门正时,缸内直喷等,我们就可以猜测它里面的复杂性了,要通过经年累月的技术积累,不断的调整演化,才能成为一项成熟的产品技术,这也是国产发动机跟国外有很大的技术差距的原因。

我们创造的任何事物和技术都处在不断的长期演变进化当中,其中有一些已经趋于稳定,比如剪刀,钳子,它们拥有简单的结构,材料结构的调整已基本最优,更多的变化空间已不大,但是我们仍然有各种针对特殊需求的剪刀设计出来,他们并没有停滞,只是稳定下来了而已。另一些还处于剧烈的变革当中,比如电视机,手机,一方面由于它们本身的复杂度导致更多的可能,另一方面因为它们还不是很完备,需要不断的技术改进,电视机经历了黑白,彩色,阴极射线管,液晶等一代又一代的技术演进,现在仍然不能说成熟稳定,还有很多调整空间。手机同样也经过的很多代,他们都仍处于演化当中。

汽车的发动机也是在不断的进化,一个很好的类比是人类的心脏,经过了亿万年的进化,现在的人类心脏是个复杂而且高效的器官,它在历史当中必定有过不同的形式,通过自然选择的不断调整,最终趋于稳定。作为一种用金属构造的充满各种孔洞机构的燃烧装置,发动机经历了若干代的调整变革,不断的提升燃油利用效率,提高输出功率,跟大自然的进化类似.

如果我们仔细的考察一些就会发现,生物的进化跟技术的演进是何等的相似!生物通过调整改变以适应自然环境,我们创造改进技术来迎合市场需求。抽去形式概念,二者本质没有差别。

在各项技术产品中,汽车是跟生物最为类似且我认为最有进化潜力的一项东西。因为它可以在地球表面移动,这正是动物最重要的特性。

如果远古的地表拥有我们现在道路的形式,我想会有生物进化出轮子的结构,这样的行进方式最节省能量。但是崎岖不平的地表,导致腿成为现今动物界的主导。

我们认为动物之所以为动物,最主要的特征就是动物可以自由的行走移动,避开障碍,而不是具有高级思维能力。

汽车必须靠人来驾驶,但是为了便利,我们逐渐开发除了各种技术减轻人的疲劳。手动档变成自动档,简化了操作流程,定速巡航可以把脚从油门移开,自动泊车系统可以以检测周围空间把车自动倒进狭小的空间里,自适应巡航甚至可以根据前面车的距离自动调整车速跟车。这些辅助性的装置似乎都朝着一个目标,那就是自动驾驶。

想象一下,一辆汽车可以在无人的状态下自动前进,检测避开障碍,自动去加油。我们可以通过无线网络远程把车召唤到眼前,这不是不可企及的想象,未来几年极有可能实现。比如google对自动驾驶投入了很多资金进行研发,并且它的自动驾驶汽车已经安全无事故的行驶了几十万公里。

我们尝试去构造机器人,只是作为兴趣和研究,并没有强大的市场需求。同样也不会为了百分之几的性能优势去花大量时间精力去改进它的某一个部件,但是对于成熟且庞大的汽车市场就是很不同的景象了。就像语音识别随着智能手机的兴盛突然变得炙手可热起来一样,人们愿意为此去投入大量财力精力去研发。

当汽车的自动驾驶成为可能,我们就会考虑如何添加更多的自主性进去了。模式识别(比如现在一些高档车配备的交通路牌识别技术),语音识别,更高级的智能等,都会随之而来。

我可以大胆的预测,将来机器人和人工智能等技术,一定是因为汽车而发展起来,汽车本来就是一个很好的机器人。

为什么是汽车而不是手机或者电视机呢?在我们可以预见的未来,以及事物发展的趋势,我们可以清晰的看到他们各自朝前发展的脉络,以及人们对这些事物功能的期望。电视机被赋予了更轻薄便利色彩真实的期许,手机也是操作反应的功能性需求,而汽车,人类更希望下放更多的权利和自主性过去,通过自动化为生活提供便利。可以说,汽车已经被选定了一条自动化的道路,一条导致智能化自动机器的前进途径。

动物和汽车,器官和部件,形成绝佳的对应类比:心脏和发动机,轮子和脚,关节和离合器差速器,食物和燃油……零件的不断调整改进就是进化。也许有一天,就像变形金刚里,我们会引入汽车人这个称谓。

在linode买了台vps,加州fremont机房,1G内存,24G硬盘,xeon L5520 cpu,ping值在180ms左右,性能速度尚可。有个公网ip的机器还是很有用的,比如开一些服务,可以在任何地方连上去,或者开vpn绕开长城。

以前在一个叫cyberultra的新加坡运营商那里买了虚拟主机,一年下来几百块前,基本还算稳定。用了三年,下个月到期,想想还是换下吧,在一个地方耗的太久,因循守旧,就像人生,总是觉得乏味。

今天在vps上装了个apache和mysql,整了整wordpress,把以前的数据导入,算是差不多搭了起来,换了个新的主题,尝试改变下。

罗列一下遇到几个小问题,一个是permlink改变成非?打头的话,会导致404错误,找不到页面。仔细找了下,是.htaccess文件里的重写规则没有生效,在apache的配置文件的Directory项里,AllowOverride None会把这个选项关闭,改成AllowOverride All就可以打开了。另外还要注意看下apache的rewrite模块有没有打开。

另一个是theme的问题,右边的widget里都有一个Click to view/hide的头,看起来很不协调。懒得去慢慢看代码修改了,先将就着,改天再换个主题用吧。自从眼睛出问题以来,心情精力严重下降,没有当初巨细靡遗的折腾劲了。

现在微博微信大行其道,博客开始变得越来越小众,就像某种古老的技术一样渐渐淡出。我不喜欢微博,一大堆无用信息,把精力都耗费在看别人唠家常上了,加上眼睛不好,手机用回了nokia黑白屏,似乎跟这个时代格格不入。从个人而言,这些新型的媒体或者社交形式,除了把空闲时间套牢,信息量实在微乎其微。

我想博客还会继续存在,就像很多有价值的东西一样,比如邮件列表还是开发人员最有效的沟通方式,bbs仍然提供有价值的社区交流,博客也会继续记录个人的思想,一直作为一种概念形态凝结于未来的社会中。

今天是3.14,所谓的Pi Day,借机发一下一直思考着的几个相关问题吧。

我的高中数学老师给出了一个有趣的问题, 咋一看是如此的简单以至于可以作为小学生的填空题: 1和0.9循环哪个大?很多人会不假思索的认为1要大那么一点点, 而事实上这两个值是严格的相等。可以这么证明:
1/3=0.3333….. 三分之一等与0.3循环,这个是我们都认为正确的结果,然后等号两边都乘以3
3 * 1/3 = 3 * 0.333333…… 就得出
1 = 0.999999……
这是一个让人惊讶的事实,跟我们的直觉不相符,但我们很容易接受推导过程。
推导过程中有一个小陷阱,就是把乘法自然而然的推广到了无穷项并且不认为有什么不妥。
为什么无穷项的表现总是让人觉得匪夷所思?

我们对数字以及相应的操作法则,必定源于大脑的思维模型,绝不仅仅是后天得到的知识那么简单,应该牵涉到了大脑的某种本质的先天性的结构相关的东西,数学是对这些基础法则的抽象表达和推导。

如果有一系列的个体,挨个排开,我们对每一个不同的个体用一个标记来代表它,比如第一个就是符号1,第二个符号就是2,这样我们就得到一个序列
1 2 3 4 5 6 7 ……..
我们说自然数序列是什么呢,就是无穷个体的一系列标签,我们对这个群体的若干操作,就是对物理世界若干个体的不同操作,被抽象出来加减乘除等法则。比如,大街上站着一个人,我们看到并认为如此,一些动物,比如狗可能也能察觉到,这时候又来了一个人,这时候我们认为,这跟刚才肯定不同,可能狗也这么认为。同时,树上有一只鸟,又飞过来一只,我们开始总结两者的共同之处并说:这两者在数量上是相同的。狗会怎么认为?可能我们并不知道,也许它有这种抽象能力只是无法表述出来。但大部分人会觉得从中抽象出来个体和计数跟人类的智能是绑定在一起的。

我们一开始教小学生数学,书上画着三个苹果下面写着3,画着三棵树下面写着3,画着三只蝴蝶下面写着3,然后老师告诉学生3,这是3,比来比去。小孩子很容易就接受理解了,并自发的产生并获得3这个概念。某些本质的东西,是没有办法解释的,就像我们教育小孩子一样,通过一系列的共同引发他们自己的抽象。人类大脑构建了某些基础性的东西,而我们后天向其中诱导灌输知识文明。

数字是一种抽象,自然中的个数在大脑中的某种表示。但对计算机来说,数字与自然界并没有任何关联,只不过是一组寄存器的状态,加减乘除也是硬编码的随着时钟周期变化状态的某些法则。所以我们认为通用图灵机随着外界输入改变并产生输出,只是状态变迁,跟钟表,复杂的齿轮结构,没有太多两样。智慧的本质也许并不仅仅是物质那么简单,可能会引入某些比如灵魂之类的更深刻的问题,先不跑题了。

整数的无穷序列,就是1,2,3…..跟我们所能感知到的物理世界,在大脑模型中似乎是对应的,无数个数目组成树林,无数的树叶,草,生物,都能通过这个序列一一对应上,就是数出来,光、烟雾之类的虽然不能数,但必定有另一类机制处理,我们说一朵云,一柱烟,抽象之后还是归类的这个序列上。

这个整数序列专业术语来讲就是可数集,我们认知上的物理世界是可数的。
通过人类对世界的认知思考,引入了新的问题,在一个二维平面内,到一个点距离相等的所有点的集合,我们称作圆,丈量这个闭合曲线的长度,引入一个我们无法表达的数字,就是pi,我们无法用数字形式表示出来它,因为它的后面有无穷个位数,3.141592653589793238462643383279502884197169399375105820974944592307…一直写下去,从耗费时间的维度上是无限的,这跟图灵停机问题有些类似。
但是我们同样可以思维感知它,通过一个符号pi,我们就能思考处理它,并引入各种各样的算术操作表达式当中,大脑解决问题的模式似乎就是,概念的概念,任何问题都可以通过添加一层更高的抽象来解决,这可能跟神经元的连接模式有关。

任何整数的加减乘除表达式都可以写成小数的形式,比如前面说的1可以写成0.9循环,1/3可以写为0.3循环,等等,但是这些小数都有循环的规律。如果小数点后的不同位是任意的数字,我们就得到了一个更为诡异的大的数字系统,比如说0和1之间的所有小数,构成所谓的连续统,通常我们认为这个集合是不可数的,这个可以通过康托对角线法则来证明。
连续统以及相关的问题是个复杂的课题,牵涉到公理化集合论,连续统假设等。
单从一个无限不循环的小数后的数字序列来看,可以认为是一个可数集,而这些实数似乎有无穷个,无穷的无穷。我隐约的感觉这些似乎跟图灵停机问题、可计算性,甚至更深刻的智能的本原等有着异曲同工之处。

假如我们能够通过一个无穷的数字序列来描述一个原子的状态,比如动量、空间位置、电子轨道等信息,那么构成整个宇宙的所有原子,就能排成一串数字的序列,如果把时间划分成细片,就像时钟最短的嘀嗒,这一串数字在时间的维度上又构成一个序列。这个序列是否能描述我们的宇宙?或者说,这个序列能用实数集来表示么?还是需要比连续统更高的势?当然我们不可能得到每个原子的精确信息,这里只是想从另一个角度来看一下。

生命就是要在复杂的序列中找出某种规律,毫无规律的东西我们也不认为具有考虑的价值。pi是一种规律性的东西,虽然我们不能用有限的整数四则运算来表示它,但是可以用无穷级数来写出,如果引入一些三角函数和微积分等高级一点的算符,就更容易了,比如

或者

推导演算,这些怪异的数字就是这么得出来的,在一种表示下是有序的事物,但是到了另一种角度,却成了毫无意义的无穷序列,如果我们看一下自然界的一些现象也是如此,而智慧生命的本来意义就在于能从这些无序之中归类整理出来某些规律,这是生命的本质还是由之产生的属性?

最近在调一个性能问题,过程中惊讶的发现,cpu竟然能够在一个时钟周期里执行多条指令。

仔细google后发现还是我土了,这是cpu早就支持的一项技术,叫做superscalar,超标量。其实上学时计算机组成原理就翻来覆去的说这个概念,我一直理解为,超标量就是一条指令可以操作多条数据,进而达到一个时钟周期内达到几条指令的效果,而这其实是SIMD所实现的功能。

写了个测试程序仔细研究了下。一个for循环在编译器不开优化选项的情况下,大致翻译成六条指令
[code]
for(unsigned i=0; i<0xffffffff; ++i);
00FC1040 mov dword ptr [i],0
00FC1047 jmp test_cpu+42h (0FC1052h)
00FC1049 mov eax,dword ptr [i]
00FC104C add eax,1
00FC104F mov dword ptr [i],eax
00FC1052 cmp dword ptr [i],0FFFFFFFFh
00FC1056 jae test_cpu+4Ah (0FC105Ah)
00FC1058 jmp test_cpu+39h (0FC1049h)
[/code]
在我的机器,core i5-2400 @ 3.1GHz的cpu上,这个循环跑了8496ms,每秒钟执行的指令条数为0xffffffff*6/8.496=3033168993.644068,平均1.022个时钟周期执行一条指令,事实上还达不到,因为intel的core系列cpu支持Turbo Boost技术,会动态条整cpu的频率,i5-2400可以达到3.4 GHz,一般来讲,差不多也就是1.2个时钟周期执行一条指令。

如果for循环里做几个操作,看下面代码
[c]
int a=0,b=0,c=0;
for(unsigned i=0; i<0xffffffff; ++i){
++a;
++b;
++c;
}
[/c]
翻译成下面的机器代码
[code]
int a=0,b=0,c=0;
0104A0E0 mov dword ptr [a],0
0104A0E7 mov dword ptr [b],0
0104A0EE mov dword ptr [c],0
for(unsigned i=0; i<0xffffffff; ++i){
0104A0F5 mov dword ptr [i],0
0104A0FC jmp test_cpu+57h (104A107h)
0104A0FE mov eax,dword ptr [i]
0104A101 add eax,1
0104A104 mov dword ptr [i],eax
0104A107 cmp dword ptr [i],0FFFFFFFFh
0104A10B jae test_cpu+7Ah (104A12Ah)
++a;
0104A10D mov eax,dword ptr [a]
0104A110 add eax,1
0104A113 mov dword ptr [a],eax
++b;
0104A116 mov eax,dword ptr [b]
0104A119 add eax,1
0104A11C mov dword ptr [b],eax
++c;
0104A11F mov eax,dword ptr [c]
0104A122 add eax,1
0104A125 mov dword ptr [c],eax
}
0104A128 jmp test_cpu+4Eh (104A0FEh)
[/code]
一共是9+6=15条指令,执行时间为9795ms,一秒内总共执行0xffffffff*15/9.795=6577285290.964778条指令,3.1GHz的cpu来看,平均一个时钟周期执行两条指令。

可以接着扩展,比如
[cpp]
int a=0,b=0,c=0,e=0,f=0,g=0;
for(unsigned i=0; i<0xffffffff; ++i){
++a; ++b; ++c; ++e; ++f; ++g;
}
[/cpp]

被翻译成24条指令,10611ms,总条数为0xffffffff*24/10.611=9714373299.406277,平均一个时钟周期执行3条指令。

指令在执行阶段,会被分析数据依赖关系,可以并行的就直接被dispatch到ALU乱序执行。上面的a,b,c三个变量之间没有以来关系,于是就可以发挥superscalar的功效了。

但是如果a,b,c三个变量之间产生关联,就会变成顺序执行了,比如
[cpp]
int a=0,b=0,c=0;
for(unsigned i=0; i<0xffffffff; ++i){
a = b+c;
b = a+c;
c = a+b;
}
[/cpp]

同样编译成15条指令
[code]
for(unsigned i=0; i<0xffffffff; ++i){
00A4A0F5 mov dword ptr [i],0
00A4A0FC jmp test_cpu+57h (0A4A107h)
00A4A0FE mov eax,dword ptr [i]
00A4A101 add eax,1
00A4A104 mov dword ptr [i],eax
00A4A107 cmp dword ptr [i],0FFFFFFFFh
00A4A10B jae test_cpu+7Ah (0A4A12Ah)
a = b+c;
00A4A10D mov eax,dword ptr [b]
00A4A110 add eax,dword ptr [c]
00A4A113 mov dword ptr [a],eax
b = a+c;
00A4A116 mov eax,dword ptr [a]
00A4A119 add eax,dword ptr [c]
00A4A11C mov dword ptr [b],eax
c = a+b;
00A4A11F mov eax,dword ptr [a]
00A4A122 add eax,dword ptr [b]
00A4A125 mov dword ptr [c],eax
}
00A4A128 jmp test_cpu+4Eh (0A4A0FEh)
[/code]
但是却花了28410ms才执行完,0xffffffff*15/28.410=2267670166.3146777,执行一条指令需要1.367个时钟周期。

查了下intel的Software Developer’s Manual关于superscalar的说明

2.2.3.2 Execution Core
The execution core of the Intel Core microarchitecture is superscalar and can process instructions out of order to increase the overall rate of instructions executed per cycle (IPC). The execution core employs the following feature to improve execution throughput and efficiency:

• Up to six micro-ops can be dispatched to execute per cycle
• Up to four instructions can be retired per cycle
• Three full arithmetic logical units
• SIMD instructions can be dispatched through three issue ports
• Most SIMD instructions have 1-cycle throughput (including 128-bit SIMD instructions)
• Up to eight floating-point operation per cycle
• Many long-latency computation operation are pipelined in hardware to increase overall throughput
• Reduced exposure to data access delays using Intel Smart Memory Access

core架构的cpu一共有3个算术逻辑单元ALU,每个cycle最多可以并发6条微指令。

wikipedia上的介绍讲1998年以后的通用cpu,除了低功耗和嵌入式的以外,基本都支持superscalar技术。

其实现在一些高性能的嵌入式cpu也支持超标量了,比如iphone 4使用的A4处理器,包含一个ARM Cortex-A8内核,是一个dual-issue superscalar design,每个周期可以并发执行两条指令。

2012年最后一天了

这一年,工作,生活,都是惨不忍睹,健康问题更是每日折磨。

不多总结了,总之,这一年是人生谷底,希望明年会好一些。