sunpinyin-2.0.3 released

在漫长的RC之后,sunpinyin社区release了2.0.3版本…

Quoted from sunpinyin.org:

2.0.3 release is containing a lot of major fix compare to last release. User should update to this release as soon as possible. It fixed many inconveniet bugs. Changes compare to 2.0.2 are described below:

Build:

  • CFLAGS, CXXFLAGS and LDFLAGS are recongnized.
  • Scons scripts now will remember the configuration arguments in configure.conf.
  • Ported to ARMEL architecture.
  • Able to build on FreeBSD.

libsunpinyin:

  • New LOGO!
  • History cache focus more on recent commits.
  • Supports --libdir and --libdatadir as configuration arguments.
  • Hunpin support. (Contributed by Hanjie Xu)
  • Fixed weird behavior of history with a single character.
  • Fixed a potential issue for candidate ranking.

ibus-sunpinyin:

  • Supports --libdir, --datadir, --execdir as configuration arguments.
  • Alt+num key as the candidate delete key for ibus-sunpinyin.
  • Able to build on IBus-1.4

xsunpinyin:

  • Synchronized the version between xsunpinyin and libsunpinyin project.
  • Fixed startup crash with empty directory.
  • Fixed position problem on multi-screen.
  • Fixed crash on exit, which caused history information lost.
  • Refact UI system
  • Added skin support
  • Fixed text overbound when pinyin are too long.
  • Fixed ignorance of ShuangPin setting.
  • Fixed weird behavior of fast switch to english. ( Issue 213 ).

scim-sunpinyin:

  • Add legacy support for scim (Thanks to liangguo)

二分查找、区间、一致性

据说90%的程序员不能正确实现二分查找,《编程之美》里也专门有一章是来讨论二分查找的。因为要重启小组内的learning group,和同事讨论了一下,就拿二分查找来kick-off。基本来说,大家的实现都有这样那样的问题,甚至题目本身给出的函数原型都错了!

实现的要求是,假定整数数组array是从小到大排序的,查找key是否在array中,如果存在则返回其index,否则返回-1。我随手就写了一个函数的原型,

int bin_search (int *array, size_t len, int key)

当时没有仔细考虑,size_t和int表示的范围是不同的,会有溢出的问题。

基本上有两种实现的方法,一种是在[begin, end]闭区间上进行迭代(end是最后一个元素的index,即begin+len-1),找到一个中点middle之后,将区间划分为[begin, middle-1]和[middle+1, end],子区间依然是闭区间(且不包括middle);因为整数区间[begin, begin]不是空区间(包括begin这个整数),所以迭代的终止条件是begin>end。

第二种方法是在[begin, end)这个半闭半开区间上进行迭代(end为begin+len),找到一个中点middle之后,将区间划分为[begin, middle)和[middle+1, end),子区间依然是半闭半开区间(且不包括middle);因为整数区间[begin, begin)是个空区间,所以迭代的终止条件是begin==end。这种实现方式和STL中容器的迭代器是很一致的 :)

子问题和父问题保持一致性,对正确的实现二分查找来说是至关重要的。如果把握住子区间划分的正确性,自然能保证好迭代终止条件的正确性。(说来惭愧,我就曾用第二种方法时不小心把子区间的边界写错了,导致死循环。)

最后一点要注意的是,找中点时不要溢出,应该用begin + (end - begin)/2来得到中点的位置。

其实还有一点需要探讨的,就是如果数组的长度不是很长,可能直接循环顺序查找的速度更快。但是去看了solaris libc中的bsearch,并没有这样去“优化”。

十年码工路——汤森路透的短暂停留

毕业之后的9年中,我一直在Linux/Unix系统上做开发,而在路透所做的项目是在Windows平台上做并发系统。对我来说,也是一个不小的挑战。

我面试的时候觉得路透的工作环境还是不错的,工位虽然比Sun的小了很多,但是应该比IBM的要宽敞 :) 等我入职的时候才发现,IT环境却不是我的预期。例如,我没有本机的管理员权限,好在我可以安装cygwin,可以安装一些gnu的software,可以忍;不过,我的笔记本只有1G内存,这个的确有点那个了,经常要对运行的程序精打细算。原本想和IT申请自己买内存加的,但是因为IT是外包给富士通的,IT说公司条例不允许私加内存,而且他们也不负责给加。没办法了… 不过后来新来的同事基本上已经都配备2G或者4G内存了,我赶上那一波儿了。

很多人知道我去了路透,都问我是不是转行做记者了。其实我也是在面试前才了解到,路透社是汤森路透下的一个部门,公司的主要业务是信息服务,包括金融、法律、科技等方面。新闻部门在整个公司的营收中,只占很小的比例。我加入的这个团队是一个很新的团队,其中只有三位比较资深的同事,另外7人(包括我们的一线经理),都是新加入的。而我们team负责的开发项目,进度还比较紧。所以,前半年的工作任务是比较紧张的,不过心里倒是很充实 :)

我本来设想,去路透可以学习一些金融方面的知识。然而在路透的1年时间里,却始终没有充足的动力去学习;另外,我渐渐发现,程序员在路透需要了解很多的domain knowledge,才可能有比较好的职业发展。但是我却一直对这些domain knowledge提不起兴趣,学习起来很被动,自己还是喜欢钻研技术多一些。

再后来,我原来所在Sun的部门(现在是在Oracle),有一个机会。因为这个职位是一个team lead的职位,而我也希望能在management方面多一些锻炼,希望将来能有一些发展的机会。虽然回来在经济上还小有损失,考虑再三,还是决定回原来的部门了。

感谢路透的同事们,这一年多来对我的关照和帮助,我在路透学习了很多并发编程方面的知识,也开始学习使用了许多TR1的库。在我离职的前夕,部门刚刚要开始采用VC10,也就是说可以玩C++0x了。对一个于金融方面有兴趣的C++程序员来说,路透的确是一个很好的选择。

开源拼音输入法社区的大融合(libpinyin)

上次和FIT的合作,是开源社区同商业开发的合作,这次是开源社区的合作了…

SunPinyin、Novel Pinyin和iBus-Pinyin社区决定长期合作,联手创建libpinyin子项目。libpinyin致力于为中文拼音输入法提供智能整句输入的算法核心,将试图合并novel-pinyin和sunpinyin中的智能拼音整句输入算法部分,争取实现目前SunPinyin和Novel Pinyin的功能超集。

在不久的将来,libpinyin将为ibus-pinyin和sunpinyin提供智能拼音整句输入功能的支持。

Project Wiki: http://github.com/libpinyin/libpinyin/wiki
Project SCM: http://github.com/libpinyin/libpinyin
Mailing List: http://groups.google.com/group/libpinyin

另见Novel-Pinyin的官方声明:http://alex-epico.blogspot.com/2010/10/sunpinyinnovel-pinyin.html

SunPinyin Developers on ChinaDaily/Video

ChinaDaily Video频道的于辰康记者,前几日采访了SunPinyin社区的开发者,非常感谢ChinaDaily以及于先生,给我们这次难得的机会。我们在面对镜头时都变得超紧张,经常NG,耽搁了于先生很多的时间,而于先生对我们则非常耐心。

因为节目时长的原因,我们在介绍社区成员时,没能介绍全部的贡献者,主要介绍了比较活跃的几位成员,而且在介绍时还有一些小瑕疵,希望大家谅解。我们本来邀请了Phill Zhang同学,但是不凑巧他实在抽不出时间,很是遗憾。远在外地的tchaikov, jjgod和mike同学,都只能以照片形式入镜了。mike同学超骨感的,我也是借这个机会,第一次看到mike同学的真容 :) 感谢所有的contributors和用户朋友们,感谢大家对sunpinyin的支持!

FIT和SunPinyin展开全面合作

FIT和SunPinyin社区决定长期合作,联手制作下一个版本的FIT中文输入法。在合作中,FIT将使用SunPinyin的核心组件作为FIT的拼音输入引擎,完全替换掉旧版的fitx拼音引擎。新的拼音引擎将应用在FIT的Mac版、iPhone版和即将推出的iPad版。

对SunPinyin社区来说,SunPinyin的Mac版本将不会作为社区的工作重心,从而将更多的将精力集中到引擎、算法本身的改进中去,并全力协同FIT整合sunpinyin的输入引擎。FIT团队也会积极参与到引擎的改进和完善中,并将会负责SunPinyin-for-Mac的用户支持工作。SunPinyin-for-Mac依然遵循CDDL+LGPLv2.1,合作并不会妨碍任何有兴趣改进/完善它的朋友,贡献自己的努力。

另见FIT官方网站的声明

FAQ:

Q0. 为什么会有此次合作,这次合作有得到所有sunpinyin贡献者的认可吗?

应该说FIT和SunPinyin-mac是mac平台上使用最广泛的free的拼音输入法,FIT的开发团队长于前端功能以及用户体验上的开发,sunpinyin社区长于输入引擎的算法。两个团体的合作,会融合两者的长处,打造更好的mac平台以及iOS平台上的拼音输入法。

关于合作的事宜,sunpinyin社区主要的、活跃的contributors,有经过详细的讨论,大家都充分表达了各自的意见;多数contributor都支持这一合作。

Q1. sunpinyin-mac被放弃了么?

我更愿意将其解读为,FIT放弃了其自身的拼音引擎,转而采用sunpinyin的输入引擎;同时FIT团队也会积极参与到引擎的改进和完善的工作中,以及支持原有的sunpinyin-mac用户。sunpinyin的社区力量相比来说更加壮大了。sunpinyin-mac依然遵循CDDL+LGPLv2.1,合作并不会妨碍任何有兴趣改进/完善它的朋友,贡献自己的努力。

Q2. sunpinyin和fit的合作是因为收到Goopy的压力么?

fit和sunpinyin的合作意向,在Goopy“泄露”之前就已经达成了。sunpinyin的主要贡献者,基本上都是纯粹为了爱好和兴趣,我们的目标一直是,做最好的、开源的拼音输入法;Goopy的压力只会成为我们的动力,激励我们继续努力 :)

发布SunPinyin-MacOS-2.0.2.1008 (10.5/10.6)

本次更新的主要内容包括:

  1. 加入了关闭/打开内模糊切分的选项
  2. 加入了使用backspace取消用户选择的选项
  3. 升级系统词库和语言模型至open-gram 0.1.22
  4. 解决了Sparkle升级时无法打开安装包的问题
  5. 加入了小鹤双拼方案的支持
  6. bugfixes若干

功能方面和上次在twitter上放出的RC版本,没有什么不同,主要是将数据文件更新至了open-gram 0.1.22。虽然Sparkle升级时无法打开安装包的问题已经解决,但是得等到下一次更新的时候才能起作用;所以,烦请大家不要通过自动升级来安装,而是直接下载pkg包来安装 …

欢迎大家下载试用

导入sogou输入法的细胞词库

首先请下载这个导入工具,解压缩到某个目录中。从pinyin.sogou.com下载细胞词库(scel格式),保存在某个目录中。然后在terminal中执行下面的操作:

$ python import_sogou_celldict.py PATH_TO_CELL_DICT.scel

感谢中文社区其他开发者和项目reverse engineering的工作,

TBB Study Notes (2)

tbb::concurrent_vector

stl::vector相比,tbb::concurrent_vector不支持inserterase操作,且不保证内存是连续的。因为不支持insert操作,故而无法实现由一个线程进行插入排序,并同时由另一个线程去遍历的场景。TBB中也没有平衡树的支持,估计是因为,插入/删除时的节点移动操作很多,细粒度锁不容易带来更佳性能的原因。

template<typename T, class A>
class concurrent_vector: protected internal::allocator_base<T, A>,
                         private internal::concurrent_vector_base;

typedef concurrent_vector_base_v3 concurrent_vector_base;
// VC10 defines its own v4 template

struct concurrent_vector_base_v3::segment_t {
void* array;
};

atomic<segment_t*> my_segment;
segment_t my_storage[pointers_per_short_table]; 
// pointers_per_short_table = 3

concurrent_vector_base_v3::concurrent_vector_base_v3():

将指针数组my_storage的元素赋值为NULL, 然后将my_storage赋值给my_segment。

concurrent_vector_base_v3::segment_index_of(index):

即 log2(index|1)

concurrent_vector_base_v3::segment_base (k):

(1 << k & ~1),和2**k(即1<<k)不同,当k为0时,结果为0而不是1

concurrent_vector_base_v3::segment_base_index_of(index):

将index调整为segment内的索引,并返回是第几个segment。

concurrent_vector_base_v3::segment_size(k):

返回第k个segment的大小。1 << k,k==0时应该返回2才对呀

从逻辑上看,concurrent_vector内部的segments布局如下,总会是2,2,4,8,16,32...

但是实际分配的空间,则可能是16,16,32,64,取决于第一次的reservation, growth 或 assignment操作。如果第一次要求分配10个元素,那么heap上分配的空间是,比10大的最小的2的幂数,即16。

(插图来自http://blogs.msdn.com/b/nativeconcurrency,VC10中的concurrent_vector和TBB中的是同出一脉的。)

concurrent_vector::push_back (item)

调用internal_push_back(sizeof(T), k)去分配一段空间,然后调用internal_loop_guide(ntrails为1)将item拷贝到分配的空间上,最后返回iterator

concurrent_vector_base_v3::internal_push_back(element_size, &index)

使用__TBB_FetchAndIncrementWacquire将m_early_size加1,并将原来的size赋值给tmp和index。调用helper::extend_table_if_necessary(*this, k_old, tmp),在必要时扩展segment table,调用helper::acquire_segment获取一个segment的基地址,计算偏移并返回对应的地址。

libittnotify是一些profiling的函数,在编译时可以打开或关闭。ITT=>Intel Threading Tools。