在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,每个周期可以并发执行两条指令。