RSS Feed

Posts Tagged ‘总结’

  1. 2014总结

    December 30, 2014 by xudifsd

    2014年我的关键字应该是“遇见”和“Clojure”吧。

    经历

    今年对我影响最大的一件事情就是Google Summer of Code。大二就想参加了,但是由于种种原因直到今年才真正参加,从去年十二月就开始在往届项目的idea page上去找感兴趣的项目,二三月联系mentor、提交patch,四月看类型系统的论文,五月开始,八月结束。整个过程耗费了大量的精力和时间,但是收获也是巨大的。

    之前预期的收获就是Google发的钱以及简历上可以多写点东西,但是后来发现远远不止于此,不知道其他的开源组织怎么样,但是我觉得Clojure这个组织还挺有意思:它会筹集一些钱来赞助参加了GSoC的学生去参加Clojure/conj或Clojure/west,而且社区内部似乎很多人也愿意帮助一些项目的进行,比如我做的Typed Clojure项目本身就是诞生于GSoC项目,维护者也就是我的mentor就是全职在做这个项目,靠的就是从社区筹集的资金。现在Clojure社区经常讨论的一个话题就是diversity,说现在的Clojure开发者80%都是白人男性,希望能吸引到其他的人多参与,Clojure/conj就提供这样的grant。社区本身也挺有活力,在刚开始GSoC的时候,就会有Clojure Gazette这样的媒体邮件采访做GSoC的学生,并问一些项目的问题这样。

    不过我觉得最主要的一个收获是开阔了眼界,知道了一个非公司资助的开源项目是怎么运行的,遇见了mentor,知道了他是怎么去做事情。最近才知道他现在在美国读phd,仍会继续做Typed Clojure项目,而且还计划资助几个学生兼职开发,命名为diversity scholarship,主要想资助非白人学生,增加Clojure社区的diversity,原因就是在GSoC中与不同国家的学生交互的经历很有意思(其中还提到了我,很开心,笑)。

    除了GSoC,我还通过其他的渠道遇见了很多人。

    八月的时候,国内参加了GSoC的学生还在北京聚了一次,遇见了更多有意思的人,有传说中做CERN项目的牛人、扬言只写了14行代码就完成了GSoC的大神、写gcc go前端的萌妹子。之后还参加了十一月份的hackathon,约了两个一直想面基的豆瓣友邻参加,虽然没有得奖,但是整个过程还是很有意思,认识了很多上交的学生,还认识了超厉害的前端妹子

    另外还遇见并喜欢上了一个女生,虽然最后无疾而终,但是还是很感激这段感情,让我成长了很多。最后觉得都是时辰的错啊。

    总结

    之前看一个关于Google面试tips的文章,说最好的状态就是“know a little a lot, know a lot a little”,现在觉得这话很有道理:做到了前一点才能显示自己的独特,做到了后一点才能为自己创造更多的机会。一两年前我还一直只想着找一个内核相关的工作,学Lisp完全就是副业,但是谁能想到今年我写的绝大部分代码都是Clojure?我发现,懂得各个领域的不同知识可以让你把很多知识串起来连成网络,这样很方便理解与记忆,而且这样在任何时刻你都可以不花太多时间就能把know a little的知识扩充成know some,甚至是know a lot,然后就能投入使用。这似乎和投资里的“不要把鸡蛋放在一个篮子里”的道理一样吧。

    另外我也发现了多接触些人、多看一些书的必要性,这个社会不管是资本驱动的还是技术驱动的最终还是由人构成的,了解不同的人的经验和理念会给自己带来很多启示和帮助,很可能下一个你遇见的人或书就会彻底改变你。就我而言,如果当年没读过《黑客与画家》,我也不会去学Lisp,也不会接触到Clojure,恐怕今年也就没法参加GSoC并且找到工作了吧,笑。

    希望新的一年能出一次国,最好是能参加Clojure/west,然后就是多点一点分布式系统的技能树,一直想点,但是一直没机会实施,最后就是要更多地遇见一些人,探索生命中更多的可能性。

    明年我会尽量用英文写技术相关的博客,因为发现读我博客的国人基本上都懂英文,而且用英文写博客可以扩大受众,何乐而不为呢。


  2. 近两个月总结

    June 30, 2013 by xudifsd

    最近挺忙,发现都有两个月没写博客了,当年花钱买个主机而不是建个免费博客就是为了逼自己每个月写一篇博客的,但是这两个月实在是太忙了。眼看这7月就要到了,GR也要推上断首台了。总要挤些东西出来,恩。

    之前没上过班时觉得就算上班时间也应该挺充裕,能有自己的时间做东西。但是事实是,每天早上起来后马上就去上班,下完班吃完饭就已经7点了。而且由于盯了一天电脑了,回到家实在是不想再看电脑,顶多看下kindle或纸质书。而且在coursera上报了ML的课,每天下班看点视频,周末把编程作业做了,这样一来其他空闲时间就不多了,真心佩服那些报几个coursera课的人。而且这个月又是毕业季,上半个月总要花些时间整毕业论文的东西(特别是格式。。)。

    这两个月在公司里基本上没怎么干活,都在学习(不过从明天开始美好的日子就要过去,要开始干活了)。学了clojure,看了Google很久前发的几篇论文,还看了spark的论文。虽然说是看了,不过很多都看得很浅显,没空闲时间,基本上没有在学校那种能坚持下来看一些东西,并且形成一篇好的博客或程序的,或许也是因为自己才工作,没有形成一种好的习惯吧。

    好吧,能坚持看到我废话到现在的人也不容易,给你们些可能对你们有用的东西吧,是这两个月看的分布式方面的一些总结。

    在这里的分布式,我指的是类似于Google数据中心的廉价PC服务器组成的集群,也就是cluster。

    关于为什么需要使用这样的cluster《The Datacenter as a Computer》里说得很清楚了,就是因为便宜。虽然廉价PC的错误率虽然很高,但是就算加上容错所需要多出来的PC,价格也会比硬件超好的服务器便宜。而由于硬件的错误,软件就必须在设计时考虑容错与灾难恢复,这两点也是在Google那三篇论文中强调的。Google那三篇论文加上一篇冷门论文就是、GFSBigTableMapReducechubby。他们对应的开源版本分别是HDFS、HBase、Hadoop和zookeeper。都是apache的项目,而且都用的是java,这也是为什么互联网企业会有这么多用java的。如果想真正学好分布式就需要从chubby也就是zookeeper入手,其他一些东西只是建立在它之上的,学起来对于真正的分布式似乎没太大作用,对使用开源版本倒是有些作用。所以要想自己做个分布式框架能复用的就只有chubby了,但是chubby又很底层,知道和学习的并不多。不过很多分布式的框架和一些底层都会依赖于它,比如mesos、spark(因为基于mesos)、storm等。

    再说说spark,spark的论文在,不过这篇论文介绍的主要却不是spark,而是spark的原理,论文最有意思的地方是它介绍的灾难恢复的技术,这也是分布式程序需要做最多优化和权衡的地方。另外据论文描述,使用它进行ML计算比用hadoop计算要快20倍。。当时看到这个比例就惊了,那就是说hadoop需要计算一天的东西spark一小时就能搞定诶(看完后就问我厂研究院的新员工他们拿什么计算,想推荐下这个,她竟然说具体不知道,她是拿单机算,于是我就只能呵呵呵了)。spark的缺点就是它的语言接口是scala根据评论发现spark的接口既有scala和也有python,不过豆瓣有克隆版dpark,接口是python,应该比较好用,还要问豆瓣厂工。

    所以如果是我,我会先拿chubby入手,并且看看一些使用zookeeper的程序是如何使用它的,一旦这个学会,再自己实现个什么小东西,分布式也就基本上差不多了,同时再推一个解释chubby挺好的博文


  3. pthread学习总结

    April 5, 2012 by xudifsd

    线程的坏处

    在理解线程和进程之前我就已经看了《Unix编程艺术》,并且被书的第7章吓得不浅。这一章大谈线程如何如何恶心,进程如何如何优秀云云。现摘抄几句:

    一个操作系统,如果没有灵活的IPC(进程间通讯)和使用IPC的强大传统,程序间就得通过共享结构复杂的数据实现通讯。由于一旦有新的程序加入通讯圈,圈子里的所有程序的通讯问题都必须重新解决,所以解决方案的复杂度与协作程序数量的平方成正比。更糟糕的是,其中任何一个程序的数据结构发生变化,都说不定会给其他程序带来什么隐藏的bug。

    线程成为滋生bug温床源于它们太容易知道过多彼此的内部状态。与有着独立地址空间、必须通过明确IPC进行通信的进程不同,线程没有自我封装。这样,基于线程的程序不仅产生普通的竞争问题,而且产生了新一类bug:时序依赖,要重现这些问题都极其困难,遑论修复。

    因此在学习《The Linux Programming Interface》时特意把几乎所有重要的东西都学完才开始学线程。并且要不是想要学下并发估计这辈子都不可能接触到线程了。

    整体来说,线程这个概念是在Unix存在了很久之后才引进的,所以很多Unix的概念都与线程不兼容,比如说信号。因此,如果要在程序中使用信号,那就不要使用线程;如果要使用线程就不要使用信号。否则程序会变得异常复杂。而且由于上面提到的原因,在传统的Unix平台上编程还是要避免使用线程。

    线程的好处

    线程这种技术既然存在就一定有它的好处,Raymond说它是为了解决一些进程生成代价高昂的系统的问题而产生的,有一定道理。但是POSIX都定义了它,并且今年GSOC的git项目都有Improving parallelism in various commands这样的idea,那么说明线程还是有市场的。但是这些理由都不是很充分。

    我觉得对于学习,最重要的不是知识而是思想。学习线程就能学到一些很重要的并发思想:如果你没有学过线程可能连reentrancy, thread-safy这些概念完全不懂,这是因为在进程中这些概念根本不重要,但是一旦进入线程的世界这些概念变得至关重要,否则你的程序就会出现前面Raymond提到的时序依赖bug。

    总的来说,编写传统的进程程序完全可以不在乎静态变量,全局变量,堆变量在不同函数之间如何同步,因为一个进程实体中永远只有一个函数在执行,并且这些资源在进程间都不是共享的(进程间唯一共享的资源恐怕就是文件系统了)。所以传统程序更容易编写,也更不容易出错。

    但是一旦到了多线程,上面的断言就错了:总是有多个函数在一个进程实体中执行(否则也就没有分多个线程的必要了)。所以线程需要一些诸如mutex,condition variable之类的同步方法来避免时序依赖。

    因此,写多线程程序就像执行一个非常精细的手术,如果连多线程程序都能正确编写那么写个多进程的程序简直就是小菜。并且一些其他的技术,诸如:原子操作,死锁,临界区域等也就非常容易理解了,这对于写一个并发的大系统很有好处。

    不同语言并发的实现

    Unix的传统是使用进程,而C算是Unix的附带品,所以C一般是使用fork()来实现并发,而C语言中使用线程就比较复杂,为了避免时序依赖还需要很多mutex和condition variable。但是看了python中的并发实现后就震惊了:程序有个全局的类实例queue,但是在访问这个类实例时竟然不需要使用任何mutex!看来python本来就已经把Queue设计成多线程中可以方便访问的了(这里也可以得出一个结论:要想深入理解一些内容最好从一些较低级的语言开始,如果一开始就用高级语言,而高级语言又把很多复杂的内容封装起来,那么根本就学不到什么东西),在高级语言中一般主要还是使用线程实现并发,甚至在Java中我都没发现有fork这个东西。JS的并发就更好实现了,ajax和事件驱动直接搞定一切,所以以这个为设计思想的Node可以非常轻松的实现并发。

    延伸

    从上面的一些总结可以知道:并发有线程和进程两种实现方法。但是这些方法都是最为底层的内容,编写大型系统时用到的会比较少。而现在使用的最为普遍的模型就是Google的MapReduce了,这个模型的最大好处就是并不要求使用者有很多的并发编程的经验,所有的任务分配,容错都是在系统内部解决。真正的MapReduce不是开源的,但是已经有了开源的MapReduce实现,那就是Hadoop。以后有空了应该把Hadoop学学。

    现在也只是掌握了最为基本的线程,熟悉了pthread的API而已,要深入还需要很多的功夫啊。


  4. Linux学习总结

    January 5, 2012 by xudifsd

    总是有些同学会问我一些Linux的问题,而且很多情况还要教实验室低年级的同学,但是授之以鱼不如授之以渔,所以总结一下我学Linux的经验,也方便别人查看。

    学习Linux的好处

    我总是觉得自己很幸运,因为我接触的第一个和计算机学科有关的就是Linux,在这之前从来没有接触过编程等东西,只是用电脑玩游戏而已。因此之后所有的计算机学习全是在Linux之下,包括编程,包括系统管理。为什么这样是幸运呢?我觉得主要有这些原因:

    1. Windows并不适合学习编程。
    2. 几乎所有的服务器都是使用Linux系统,这样一直使用Linux省去了还要学习的麻烦。
    3. 很多优秀的开源的软件都是最先支持Linux系统,之后再移植到各个平台上,而学习和使用这些软件可以很好地了解一些最新的技术,相反在Windows下就没有这么多的机会接触这些东西。

    说明一下第一点:虽然国内的一些技术书籍都是以Windows为平台,但是看了个讽刺你应该能了解一些吧。我觉得主要原因就是Windows下没有一个好的编辑器和编译器(虽然有好的IDE)。我强烈的觉得要想真正了解如何编程就必须了解程序如何编译和执行,而编辑器和编译器的分离可以强迫人们去了解这些,与这个分离策略相反的就是集成的开发环境,像VC++6.0,Eclipse,NetBeans,这些工具使用起来都是非常方便的,适合于进行正经的开发,但却不适合初学者,如果给刚接触编程的人装上这些IDE后让他们学习使用,他们肯定都能很快学会,因为只需要打上源代码,按下IDE上的编译、运行键就可以了,但是这样他们不知道程序到底怎么产生。上次就有个同学问我NetBeans怎么连接数据库啊?当时跟他解释半天不是NetBeans连接数据库而是Java连接而已。但是如果你在Linux中使用vim或emacs编辑再用gcc或者javac编译,那么你很容易就能知道编译的过程。通过知道这些细节可以了解程序如何运行,也能更好地理解程序的一些行为了,从而更好地学习编程。

    第二点:一般的用户完全不知道Linux是什么,因为Windows占85%以上的市场,在中国90%以上,而Linux只占1%,在中国就更少了,这些是桌面用户的统计,但是服务器方面完全相反,在Top500中使用Windows的系统也就一两台,其他的都是Unix系的,一般来说服务器都是使用Linux系统,为什么要在去管理服务器时再学Linux呢?直接把Linux作为主力操作系统完全可行,甚至连玩魔兽争霸都可以直接在Linux下用wine模拟。这样在日常使用中就可以学会Linux的系统维护,而不用再临时学习了。

    第三点:如果你看过github上的一些项目,很多项目都是支持直接在Linux上从源码进行安装,但是很少有项目都提供Windows的exe安装包,而直接从源码安装又会出现很多兼容性问题,甚至根本无法安装。就因为这一点,在Linux下可以尝试很多最新的开源软件,但是Windows绝对没有这么方便。一旦缺少这个条件你会错过很多好的学习机会。

    Shell

    Shell是Linux最重要的东西,在图形界面下一般叫做终端或者模拟终端,个回复指出了shell和terminal的区别,不过我的本意是指图形界面下叫做terminal这个名字的软件,它是个模拟终端,如果不去深究那么也可以叫它shell,不过真正的shell在现代的Linux系统也有,在Ubunut下可以使用Ctrl+Alt+F[1..7]转换,F7就是图行界面,通过ssh也可以直接连接远程shell),这个和Windows的cmd.exe很像,但是比cmd.exe要强大得多,很多Linux的工作都需要shell来完成,能够熟练使用shell可以说是非常重要的Linux技巧,这些技巧包括用管道连接各种小工具的输入输出,查询命令的参数,命令补齐,shell脚本编程等,举个例子吧,下面的代码是个shell脚本,总共不超过10行代码,它是干什么的呢?

    #!/bin/bash
    tr -cs A-Za-z\' '\n' |
    	tr A-Z a-z |
    	sort |
    	uniq -c |
    	sort -k1,1nr -k2|
    	head -n 10

    这个脚本只使用了最基本的Linux命令再加上管道实现了词频统计,输出出现次数最多的10个单词,而且速度也相当快,如果使用C语言想要这么快就必须自己实现一个能快速插入的数据结构,如果用高级点的语言如python又要非常了解库函数才能实现。所以shell脚本使用管道加上重定向可以非常快速地实现一些功能。甚至在git的早期开发中对于一些高级的功能如add,commit等都是使用shell脚本来调用C语言实现的命令来实现的,之后出于效率和可移植性的考虑才将这些shell实现用C语言重写。这个例子的意思就是:如果你能熟练掌握shell脚本,重定向,管道以及一些基本的命令就能实现很多功能,这些功能对于系统管理已经非常足够了,加上一些其他编程语言甚至还能做出一些软件的原型。

    软件的安装

    Linux安装软件和Windows完全不同,通常在Windows下找一个软件要自己上网搜索,找到华军等下载站,跳过一大堆广告,忍受一大堆弹窗广告,在广告群中找到不起眼的下载链接再下载安装,安装时还要注意不要安装附带的垃圾流氓软件,在Windows下安装软件就是这么麻烦。在Linux下如何呢?假设我要在Ubuntu下安装git软件,那么一条命令足已:

    sudo apt-get install git

    在Linux下只要知道软件名就可以直接用命令安装,所有下载安装过程全部全自动。而搜索软件呢?如果你不知道软件名,那么你到Google上搜索你要的功能,之后加个“Linux”就行,比如你要找个将rm视频格式转换成其他格式的软件,那么只要在Google搜索“视频转码 Linux”就行,只要找到软件的名字和软件使用时的参数就行。

    Linux软件安装这么方便就是因为Linux的一些发行版本有很强大的包管理软件。Linux可以使用的软件成千上万,如果都从源代码安装会耗费很多的编译时间,并且每个软件的编译、安装方法都不一样,包管理软件就是为了解决这个问题而存在的。Linux的发行版本有两种包管理方式,一种是Debian系统及衍生系统(Ubuntu等)使用的apt系统,另一种是红帽公司出的系统(RedHat,Fedora等)使用yum。具体的用法就不介绍了。

    POSIX标准

    POSIX标准的全称是Portable Operating System Interface,为什么这个标准重要呢?因为它规定了操作系统的系统调用的接口,其他任何软件能做的事情都不可能超过这个标准规定的接口所能做的事情,换句话说,这个标准几乎是规定了编程的能力,任何软件都不可能超过这个能力,因为软件都是运行在内核之上的。不过这个标准的本意并不是为了规定编程能力的边界,而是为了让所有的操作系统的内核都提供相应的接口,好让应用软件能够比较好的相互移植。在Linux下常常使用C编程就会非常熟练的使用这个标准规定的接口,就算是一些高级语言也都会提供这样类似的接口,它们也都是用这个接口来实现多进程,IO和进程间通信等功能。在Windows下用高级语言编程还好,能够接触到这些东西,但是用C恐怕根本接触不到这个标准,这样也丧失了可移植性。如果你编写的软件非常符合这个标准那么你的软件就能比较方便地移植到其他平台上。

    书籍

    说了这么多,还是那句话,授之以鱼不如授之以渔。自己看书学习比读别人博客吃别人嚼碎了的东西更有营养。这里列出我学Linux时看的一些书,希望对你们有用。

    The Linux Command Line 这本书非常适合初学Linux命令行的人看,由著名的 LinuxCommand.org网站的维护者编写,非常详细地介绍了Linux的命令行。
    鸟哥的Linux私房菜 基础学习篇 这是我看的第一本计算机相关书籍,在看这本书之前几乎不懂电脑,所以这本书一定非常适合Linux初学者,但是不像《The Linux Command Line》,它几乎介绍了所有的Linux相关主题,而不仅仅只是命令行。
    Advanced Bash-Scripting Guide 这本书更加详细地介绍了shell脚本,而不像《The Linux Command Line》只是简单介绍,里面也有很多的技巧,但是这本书很多都只是举例,分析,没什么系统性,所以读起来比较吃力,不过可以当查询的好去处。
    UNIX环境高级编程 这本书非常详细地介绍了UNIX系各个实现(BSD,Linux,Solaris)之间的差别,并且介绍了实现的原理以及POSIX标准,可以非常好地理解C语言系统调用的作用。
    The Linux Programming Interface 这本书和《UNIX环境高级编程》很像,只是更专注于Linux系统。
    Linux内核完全注释 这本书以早期内核版本作为标本,对几乎所有的内核代码都有注释,而且有非常详细的解释,如果你想了解内核实现的原理,这本书就适合你。