<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>素心如何天上月</title>
	<atom:link href="http://yongsun.me/feed/" rel="self" type="application/rss+xml" />
	<link>http://yongsun.me</link>
	<description>Yong Sun&#039;s Blog</description>
	<lastBuildDate>Tue, 24 Aug 2010 01:55:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>发布SunPinyin-MacOS-2.0.2.1008 (10.5/10.6)</title>
		<link>http://yongsun.me/2010/08/%e5%8f%91%e5%b8%83sunpinyin-macos-2-0-2-1008-10-510-6/</link>
		<comments>http://yongsun.me/2010/08/%e5%8f%91%e5%b8%83sunpinyin-macos-2-0-2-1008-10-510-6/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 14:07:00 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[Input Method]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[sunpinyin-2.0]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1506</guid>
		<description><![CDATA[本次更新的主要内容包括： 加入了关闭/打开内模糊切分的选项 加入了使用backspace取消用户选择的选项 升级系统词库和语言模型至open-gram 0.1.22 解决了Sparkle升级时无法打开安装包的问题 加入了小鹤双拼方案的支持 bugfixes若干 功能方面和上次在twitter上放出的RC版本，没有什么不同，主要是将数据文件更新至了open-gram 0.1.22。虽然Sparkle升级时无法打开安装包的问题已经解决，但是得等到下一次更新的时候才能起作用；所以，烦请大家不要通过自动升级来安装，而是直接下载pkg包来安装 … 欢迎大家下载试用 …]]></description>
			<content:encoded><![CDATA[<p>本次更新的主要内容包括：</p>
<ol>
<li>加入了关闭/打开内模糊切分的选项</li>
<li>加入了使用backspace取消用户选择的选项</li>
<li>升级系统词库和语言模型至open-gram 0.1.22</li>
<li>解决了Sparkle升级时无法打开安装包的问题</li>
<li>加入了小鹤双拼方案的支持</li>
<li>bugfixes若干</li>
</ol>
<p>功能方面和上次在twitter上放出的RC版本，没有什么不同，主要是将数据文件更新至了open-gram 0.1.22。虽然Sparkle升级时无法打开安装包的问题已经解决，但是得等到下一次更新的时候才能起作用；所以，烦请大家不要通过自动升级来安装，而是直接下载pkg包来安装 …</p>
<p>欢迎大家<a href="http://code.google.com/p/sunpinyin/downloads/detail?name=SunPinyin-MacOS-2.0.2.1008.zip">下载试用</a> …</p>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/08/%e5%8f%91%e5%b8%83sunpinyin-macos-2-0-2-1008-10-510-6/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>导入sogou输入法的细胞词库</title>
		<link>http://yongsun.me/2010/07/%e5%af%bc%e5%85%a5sogou%e8%be%93%e5%85%a5%e6%b3%95%e7%9a%84%e7%bb%86%e8%83%9e%e8%af%8d%e5%ba%93/</link>
		<comments>http://yongsun.me/2010/07/%e5%af%bc%e5%85%a5sogou%e8%be%93%e5%85%a5%e6%b3%95%e7%9a%84%e7%bb%86%e8%83%9e%e8%af%8d%e5%ba%93/#comments</comments>
		<pubDate>Thu, 15 Jul 2010 16:05:48 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[Input Method]]></category>
		<category><![CDATA[cell dict]]></category>
		<category><![CDATA[importer]]></category>
		<category><![CDATA[sogou]]></category>
		<category><![CDATA[sunpinyin-2.0]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1496</guid>
		<description><![CDATA[首先请下载这个导入工具，解压缩到某个目录中。从pinyin.sogou.com下载细胞词库（scel格式），保存在某个目录中。然后在terminal中执行下面的操作： $ python import_sogou_celldict.py &#60;path to your cell_dict.scel&#62; 感谢中文社区其他开发者和项目reverse engineering的工作， http://code.google.com/p/imewlconverter http://code.google.com/p/ibus-cloud-pinyin http://forum.ubuntu.org.cn/viewtopic.php?f=8&#38;t=250136&#38;start=0]]></description>
			<content:encoded><![CDATA[<p>首先请<a href="http://sunpinyin.googlecode.com/files/sunpinyin_importer.tar.bz2">下载这个导入工具</a>，解压缩到某个目录中。从<a href="http://pinyin.sogou.com">pinyin.sogou.com</a>下载细胞词库（scel格式），保存在某个目录中。然后在terminal中执行下面的操作：</p>
<p style="padding-left: 30px;">$ python import_sogou_celldict.py &lt;path to your cell_dict.scel&gt;</p>
<p>感谢中文社区其他开发者和项目reverse engineering的工作，</p>
<ul>
<li><a href="http://code.google.com/p/imewlconverter">http://code.google.com/p/imewlconverter</a></li>
<li><a href="http://code.google.com/p/ibus-cloud-pinyin">http://code.google.com/p/ibus-cloud-pinyin</a></li>
<li><a href="http://forum.ubuntu.org.cn/viewtopic.php?f=8&amp;t=250136&amp;start=0">http://forum.ubuntu.org.cn/viewtopic.php?f=8&amp;t=250136&amp;start=0</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/07/%e5%af%bc%e5%85%a5sogou%e8%be%93%e5%85%a5%e6%b3%95%e7%9a%84%e7%bb%86%e8%83%9e%e8%af%8d%e5%ba%93/feed/</wfw:commentRss>
		<slash:comments>66</slash:comments>
		</item>
		<item>
		<title>volatile, barriers and more &#8230;</title>
		<link>http://yongsun.me/2010/06/volatile-barriers-and-more/</link>
		<comments>http://yongsun.me/2010/06/volatile-barriers-and-more/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 10:25:00 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[c++]]></category>
		<category><![CDATA[concurrency]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1494</guid>
		<description><![CDATA[This is my reading notes of &#8220;Concurrent Programming on Windows&#8221;, as I said before, I am quite a newbie on this area, there maybe errors in my understanding and summary, please kindly point them out if there is any.]]></description>
			<content:encoded><![CDATA[<p>This is my reading notes of &#8220;Concurrent Programming on Windows&#8221;, as I said before, I am quite a newbie on this area, there maybe errors in my understanding and summary, please kindly point them out if there is any.</p>
<p><iframe src="http://docs.google.com/present/embed?id=ahtgvwdt62tk_267c3392wtv&#038;size=m" frameborder="0" width="555" height="451"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/06/volatile-barriers-and-more/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>TBB Study Notes (2)</title>
		<link>http://yongsun.me/2010/06/tbbconcurrent_vector/</link>
		<comments>http://yongsun.me/2010/06/tbbconcurrent_vector/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 06:06:56 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[c++]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[tbb]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1466</guid>
		<description><![CDATA[tbb::concurrent_vector 和stl::vector相比，tbb::concurrent_vector不支持insert和erase操作，且不保证内存是连续的。因为不支持insert操作，故而无法实现由一个线程进行插入排序，并同时由另一个线程去遍历的场景。TBB中也没有平衡树的支持，估计是因为，插入/删除时的节点移动操作很多，细粒度锁不容易带来更佳性能的原因。 template&#60;typename T, class A&#62; class concurrent_vector: protected internal::allocator_base&#60;T, A&#62;, 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&#60;segment_t*&#62; 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&#124;1) concurrent_vector_base_v3::segment_base (k): (1 &#60;&#60; k &#38; ~1)，和2**k（即1&#60;&#60;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 &#60;&#60; [...]]]></description>
			<content:encoded><![CDATA[<h1>tbb::concurrent_vector</h1>
<p>和<code>stl::vector</code>相比，<code>tbb::concurrent_vector</code>不支持<code>insert</code>和<code>erase</code>操作，且不保证内存是连续的。因为不支持insert操作，故而无法实现由一个线程进行插入排序，并同时由另一个线程去遍历的场景。TBB中也没有平衡树的支持，估计是因为，插入/删除时的节点移动操作很多，细粒度锁不容易带来更佳性能的原因。</p>
<pre name="code" class="cpp">template&lt;typename T, class A&gt;
class concurrent_vector: protected internal::allocator_base&lt;T, A&gt;,
                         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&lt;segment_t*&gt; my_segment;
segment_t my_storage[pointers_per_short_table];
// pointers_per_short_table = 3</pre>
<p><strong>concurrent_vector_base_v3::concurrent_vector_base_v3()</strong>:</p>
<blockquote><p>将指针数组my_storage的元素赋值为NULL, 然后将my_storage赋值给my_segment。</p></blockquote>
<p><strong>concurrent_vector_base_v3::segment_index_of(index):</strong></p>
<blockquote><p>即 log2(index|1)</p></blockquote>
<p><strong>concurrent_vector_base_v3::segment_base (k):</strong></p>
<blockquote><p>(1 &lt;&lt; k &amp; ~1)，和2**k（即1&lt;&lt;k）不同，当k为0时，结果为0而不是1</p></blockquote>
<p><strong>concurrent_vector_base_v3::segment_base_index_of(index):</strong></p>
<blockquote><p>将index调整为segment内的索引，并返回是第几个segment。</p></blockquote>
<p><strong>concurrent_vector_base_v3::segment_size(k):</strong></p>
<blockquote><p>返回第k个segment的大小。1 &lt;&lt; k，<span style="background-color: #ffff00;">k==0时应该返回2才对呀</span>？</p></blockquote>
<p>从逻辑上看，concurrent_vector内部的segments布局如下，总会是2,2,4,8,16,32&#8230;</p>
<p><a href="http://blogs.msdn.com/b/nativeconcurrency/archive/2010/01/16/concurrent-vector-and-concurrent-queue-explained.aspx"><img class="alignnone" src="http://blogs.msdn.com/blogfiles/nativeconcurrency/WindowsLiveWriter/concurrent_vectorandconcurrent_queueexpl_F57F/fig1_thumb.jpg" alt="" width="500" height="185" /></a></p>
<p>但是实际分配的空间，则可能是16,16,32,64，取决于第一次的reservation, growth 或 assignment操作。如果第一次要求分配10个元素，那么heap上分配的空间是，比10大的最小的2的幂数，即16。</p>
<p><a href="http://blogs.msdn.com/b/nativeconcurrency/archive/2010/01/16/concurrent-vector-and-concurrent-queue-explained.aspx"><img class="alignnone" src="http://blogs.msdn.com/blogfiles/nativeconcurrency/WindowsLiveWriter/concurrent_vectorandconcurrent_queueexpl_F57F/fig2_thumb.jpg" alt="" width="500" height="205" /></a></p>
<p><a href="http://blogs.msdn.com/b/nativeconcurrency/archive/2010/01/16/concurrent-vector-and-concurrent-queue-explained.aspx"></a>（插图来自<a href="http://blogs.msdn.com/b/nativeconcurrency">http://blogs.msdn.com/b/nativeconcurrency</a>，VC10中的concurrent_vector和TBB中的是同出一脉的。）</p>
<p><strong> concurrent_vector::push_back (item)</strong></p>
<blockquote><p>调用internal_push_back(sizeof(T), k)去分配一段空间，然后调用internal_loop_guide（ntrails为1）将item拷贝到分配的空间上，最后返回iterator</p></blockquote>
<p><strong>concurrent_vector_base_v3::internal_push_back(element_size, &amp;index)</strong></p>
<blockquote><p>使用__TBB_FetchAndIncrementWacquire将m_early_size加1，并将原来的size赋值给tmp和index。调用helper::extend_table_if_necessary(*this, k_old, tmp)，在必要时扩展segment table，调用helper::acquire_segment获取一个segment的基地址，计算偏移并返回对应的地址。</p></blockquote>
<p>libittnotify是一些profiling的函数，在编译时可以打开或关闭。ITT=&gt;Intel Threading Tools。</p>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/06/tbbconcurrent_vector/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>【紧急更新】SunPinyin-MacOS-2.0.2 (10.5/10.6) Patch 1</title>
		<link>http://yongsun.me/2010/06/%e3%80%90%e7%b4%a7%e6%80%a5%e6%9b%b4%e6%96%b0%e3%80%91sunpinyin-macos-2-0-2-10-510-6-patch-1/</link>
		<comments>http://yongsun.me/2010/06/%e3%80%90%e7%b4%a7%e6%80%a5%e6%9b%b4%e6%96%b0%e3%80%91sunpinyin-macos-2-0-2-10-510-6-patch-1/#comments</comments>
		<pubDate>Thu, 03 Jun 2010 14:46:52 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[Input Method]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[sunpinyin-2.0]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1459</guid>
		<description><![CDATA[非常灰常抱歉，昨天（06/02）发布的2.0.2中发现有一个crash的bug，感谢@fishwang同学的bug report。我刚刚fix了这个bug（#134），并上传了最新的2.0.2的完整安装包，原链接不变。烦请您重新下载安装，对给您带来的不便，实在是万分抱歉]]></description>
			<content:encoded><![CDATA[<p>非常灰常抱歉，<a href="http://yongsun.me/2010/06/%e5%8f%91%e5%b8%83-sunpinyin-macos-2-0-2-10-510-6/">昨天（06/02）发布的2.0.2</a>中发现有一个crash的bug，感谢<a href="http://twitter.com/fishywang">@fishwang</a>同学的bug report。我刚刚fix了这个bug（<a href="http://code.google.com/p/sunpinyin/issues/detail?id=134">#134</a>），并上传了最新的2.0.2的完整安装包，<a href="http://code.google.com/p/sunpinyin/downloads/detail?name=SunPinyin-MacOS-2.0.2.zip">原链接</a>不变。烦请您重新<a href="http://code.google.com/p/sunpinyin/downloads/detail?name=SunPinyin-MacOS-2.0.2.zip">下载安装</a>，对给您带来的不便，实在是万分抱歉 <img src='http://yongsun.me/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/06/%e3%80%90%e7%b4%a7%e6%80%a5%e6%9b%b4%e6%96%b0%e3%80%91sunpinyin-macos-2-0-2-10-510-6-patch-1/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>发布 SunPinyin-MacOS-2.0.2 (10.5/10.6)</title>
		<link>http://yongsun.me/2010/06/%e5%8f%91%e5%b8%83-sunpinyin-macos-2-0-2-10-510-6/</link>
		<comments>http://yongsun.me/2010/06/%e5%8f%91%e5%b8%83-sunpinyin-macos-2-0-2-10-510-6/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 13:57:03 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[Input Method]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[sunpinyin-2.0]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1451</guid>
		<description><![CDATA[本次更新主要是对2.0.2-beta-1进行了一些修正，加入了“声母简写（z/c/s-&#62;zh/ch/sh）”的选项，也加入了全角空格的支持（尚未支持全角小写字母）。 从2.0.2开始，SunPinyin 2 for Mac 全面采用了open-gram的词库和语言模型，因此会导致您的history cache无效，您可以在执行完安装程序之后，手工删除现有的history cache文件（$ rm ~/Library/Application\ Support/SunPinyin/history）。另外一个重大的更改是，扩大了wordID的范围，使系统词库+用户词库的理论容量可以达到2^24，您现在可以放心导入比较大的个人词库了。不过这也导致了和2.0/2.0.1的词库格式不相兼容。 正是由于上面两个原因，2.0.2的安装包中，直接包括了lm_sc.t3g.le和pydict_sc.bin.le的二进制数据文件，大家可以直接安装就好。另外，sunpinyin_importer中的系统词表也更新为open-gram的词表了。 对于power的mac用户来说，我们已经解决了大端数据的生成问题，请在安装时下载相应的数据文件 &#8230; 另外，非常抱歉的是，sparkle自动升级的问题还没有来得及解决，请大家不要通过自动升级来安装，而是直接下载pkg包来安装 &#8230; 欢迎大家下载试用 &#8230;]]></description>
			<content:encoded><![CDATA[<p>本次更新主要是对<a href="http://yongsun.me/2010/05/%e6%9b%b4%e6%96%b0sunpinyin-macos-2-0-2-beta-1-10-510-6/">2.0.2-beta-1</a>进行了一些修正，加入了“声母简写（z/c/s-&gt;zh/ch/sh）”的选项，也加入了全角空格的支持（尚未支持全角小写字母）。</p>
<p>从2.0.2开始，SunPinyin 2 for Mac 全面采用了<a href="http://sunpinyin.org/open-gram">open-gram</a>的词库和语言模型，因此会导致您的history cache无效，您可以在执行完安装程序之后，手工删除现有的history cache文件（$ rm ~/Library/Application\ Support/SunPinyin/history）。另外一个重大的更改是，扩大了wordID的范围，使系统词库+用户词库的理论容量可以达到2^24，您现在可以放心导入比较大的个人词库了。不过这也导致了和2.0/2.0.1的词库格式不相兼容。</p>
<p>正是由于上面两个原因，2.0.2的安装包中，直接包括了lm_sc.t3g.le和pydict_sc.bin.le的二进制数据文件，大家可以直接安装就好。另外，<a href="http://code.google.com/p/sunpinyin/downloads/detail?name=sunpinyin_importer.tar.bz2">sunpinyin_importer</a>中的系统词表也更新为open-gram的词表了。</p>
<p>对于power的mac用户来说，我们已经解决了大端数据的生成问题，请在安装时下载相应的数据文件 &#8230; 另外，非常抱歉的是，sparkle自动升级的问题还没有来得及解决，<span style="background-color: #ffff00;">请大家不要通过自动升级来安装，而是直接下载pkg包来安装</span> &#8230;</p>
<p>欢迎大家<a href="http://code.google.com/p/sunpinyin/downloads/detail?name=SunPinyin-MacOS-2.0.2.zip">下载试用</a> &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/06/%e5%8f%91%e5%b8%83-sunpinyin-macos-2-0-2-10-510-6/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>【预告】SunPinyin做客Beta沙龙</title>
		<link>http://yongsun.me/2010/05/%e3%80%90%e9%a2%84%e5%91%8a%e3%80%91sunpinyin%e5%81%9a%e5%ae%a2beta%e6%b2%99%e9%be%99/</link>
		<comments>http://yongsun.me/2010/05/%e3%80%90%e9%a2%84%e5%91%8a%e3%80%91sunpinyin%e5%81%9a%e5%ae%a2beta%e6%b2%99%e9%be%99/#comments</comments>
		<pubDate>Thu, 27 May 2010 13:18:59 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[betasalon]]></category>
		<category><![CDATA[sunpinyin]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1444</guid>
		<description><![CDATA[http://club.blogbeta.com/2010/05/13-sunpinyin 时间：2010年6月4日星期五晚上，19: 00开始 地点：奇遇花园咖啡馆（问路电话010-88320741） 地址：西直门北展北街9号华远企业号（华远地产）D座一层（地图） 演讲题目：What’s new of SunPinyin 2.0 内容预览： 演讲人简介： 孙勇，SunPinyin项目的Lead Engineer之一，SunPinyin Mac Porting的主要维护者。 个人blog，http://yongsun.me，twitter: @yongsun 参与说明：无需报名，参加免费，点单AA]]></description>
			<content:encoded><![CDATA[<p><a href="http://club.blogbeta.com/2010/05/13-sunpinyin">http://club.blogbeta.com/2010/05/13-sunpinyin</a></p>
<p>时间：2010年6月4日星期五晚上，19: 00开始<br />
地点：奇遇花园咖啡馆（问路电话010-88320741）<br />
地址：西直门北展北街9号华远企业号（华远地产）D座一层（<a href="http://storygarden.me/cafe/map">地图</a>）</p>
<p>演讲题目：What’s new of SunPinyin 2.0</p>
<p>内容预览：</p>
<p><iframe src="http://docs.google.com/present/embed?id=ahtgvwdt62tk_269hjmtsjgb&#038;size=m" frameborder="0" width="555" height="451"></iframe></p>
<p>演讲人简介：<br />
孙勇，SunPinyin项目的Lead Engineer之一，SunPinyin Mac Porting的主要维护者。<br />
个人blog，http://yongsun.me，twitter: @yongsun</p>
<p>参与说明：无需报名，参加免费，点单AA</p>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/05/%e3%80%90%e9%a2%84%e5%91%8a%e3%80%91sunpinyin%e5%81%9a%e5%ae%a2beta%e6%b2%99%e9%be%99/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>TBB Study Notes (1)</title>
		<link>http://yongsun.me/2010/05/tbb-study-notes-1/</link>
		<comments>http://yongsun.me/2010/05/tbb-study-notes-1/#comments</comments>
		<pubDate>Thu, 27 May 2010 05:55:46 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[c++]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[tbb]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1436</guid>
		<description><![CDATA[因为工作的关系，现在对C++的并发编程十分有兴趣，TBB无疑是这一领域的佼佼者。我主要对并发容器、scalable allocator比较有兴趣。现在刚刚开始读TBB的代码，这里是一些粗浅的笔记，欢迎大家多指正 &#8230; tbb::machine tbb_machine.h中引入了所有支持平台的头文件，如果对应平台没有定义__TBB_CompareAndSwap4，__TBB_CompareAndSwap8，__TBB_Yield，或__TBB_release_consistency_helpler，就会报错，无法支持。如果没有定义__TBB_load_with_acquire或__TBB_store_with_release，就会通过__TBB_release_consistency_helpler来实现它们；如果没有实现__TBB_Pause，就通过__TBB_Yield来实现。 __TBB_rel_acq_fence和__TBB_release_consistency_helper不同，前者是一个真正的硬件的fence，后者只是为了告诉编译器不要进行重排。Intel的编译器就将__TBB_release_consistency_helper定义为空了，但是GCC需要特殊的定义。但是奇怪的是，MSDN上说_ReadWriteBarrier是包括硬件fence的。 内存语义（memory semantics）: load_with_acquire: 栅栏之后的内存操作不能移动到load之前； store_with_release: 栅栏之前的内存操作不能移动到store之后； __TBB_machine_fetchadd1等方法，通常定义在src/&#60;arch&#62;/atomic_support.asm中的，ibm_aix51中是一个C文件。 某些term和Windows API的对应关系： fetch-and-add =&#62; InterlockedExchangeAdd fetch-and-store =&#62; InterlockedExchange compare-and-swap =&#62; InterlockedCompareExchange atomic_backoff: pause()方法，在前5以内，是指数级的backoff，之后调用__TBB_Yield()来交出CPU。bounded_pause()会在5次尝试之后，返回false。 还定义了原子的OR和AND操作，以及__TBB_TryLockByte，__TBB_LockByte等辅助函数（都是基于CAS来实现的）。 tbb::atomic enum memory_semantics: {__TBB_full_fence, acquire, release}; 后面两个应该只是为支持IA64的，只有在linux_ia64.h中定义了__TBB_DECL_FENCED_ATOMICS这个宏，并实现了型如__TBB_CompareAndSwap##S##M（其中S是size，M是memory_semantic，例如__TBB_CompareAndSwap4acquire）等方法。如果这些方法没有被定义的话，tbb_machine.h中会用__TBB_full_fence语义的版本重定义之。 atomic_rep: 对长度为[2, 4, 8]字节的类型，都要求对齐；即加入了一些编译器属性。 template struct atomic_traits; 包括compare_and_swap, fetch_and_add, fetch_and_store等几个基本的方法。 atomic_impl实际上是对atomic_rep和atomic_traits的一个包装。而atomic模板从atomic_impl中派生得到的，对指针类型来说，是从atomic_impl_with_arithmetic中派生的（void *除外），以对指针的移动操作（例如++, &#8211;）进行memory barrier的保护。而atomic_impl_with_arithmetic也是从atomic_impl中派生的。相比atomic_impl，atomic对赋值操作operator=加入了fence的保护。 tbb::blocked_range 包括1维、2维、3维的实现。模板参数是iterator类型。表示一个半闭半开的区间，[my_begin, my_end)。当区间的size&#60;=my_grainsize时，区间就不可再分了。其中一个构造函数，可以将当前的range（*this）分为两半，新构造的range是后一半，旧的range被修改为前一半。]]></description>
			<content:encoded><![CDATA[<p>因为工作的关系，现在对C++的并发编程十分有兴趣，TBB无疑是这一领域的佼佼者。我主要对并发容器、scalable allocator比较有兴趣。现在刚刚开始读TBB的代码，这里是一些粗浅的笔记，欢迎大家多指正 &#8230;</p>
<h1>tbb::machine</h1>
<p>tbb_machine.h中引入了所有支持平台的头文件，如果对应平台没有定义__TBB_CompareAndSwap4，__TBB_CompareAndSwap8，__TBB_Yield，或__TBB_release_consistency_helpler，就会报错，无法支持。如果没有定义__TBB_load_with_acquire或__TBB_store_with_release，就会通过__TBB_release_consistency_helpler来实现它们；如果没有实现__TBB_Pause，就通过__TBB_Yield来实现。</p>
<p>__TBB_rel_acq_fence和__TBB_release_consistency_helper不同，前者是一个真正的硬件的fence，后者只是为了告诉编译器不要进行重排。Intel的编译器就将__TBB_release_consistency_helper定义为空了，但是GCC需要特殊的定义。但是奇怪的是，MSDN上说_ReadWriteBarrier是包括硬件fence的。</p>
<p>内存语义（memory semantics）:</p>
<p style="padding-left: 30px;">load_with_acquire: 栅栏之后的内存操作不能移动到load之前；<br />
store_with_release: 栅栏之前的内存操作不能移动到store之后；</p>
<p>__TBB_machine_fetchadd1等方法，通常定义在src/&lt;arch&gt;/atomic_support.asm中的，ibm_aix51中是一个C文件。</p>
<p>某些term和Windows API的对应关系：</p>
<p style="padding-left: 30px;">fetch-and-add    =&gt; InterlockedExchangeAdd<br />
fetch-and-store  =&gt; InterlockedExchange<br />
compare-and-swap =&gt; InterlockedCompareExchange</p>
<p>atomic_backoff: pause()方法，在前5以内，是指数级的backoff，之后调用__TBB_Yield()来交出CPU。bounded_pause()会在5次尝试之后，返回false。</p>
<p>还定义了原子的OR和AND操作，以及__TBB_TryLockByte，__TBB_LockByte等辅助函数（都是基于CAS来实现的）。</p>
<h1>tbb::atomic</h1>
<p>enum memory_semantics: {__TBB_full_fence, acquire, release};</p>
<p>后面两个应该只是为支持IA64的，只有在linux_ia64.h中定义了__TBB_DECL_FENCED_ATOMICS这个宏，并实现了型如__TBB_CompareAndSwap##<strong><span style="color: #0000ff;">S</span></strong>##<strong><span style="color: #ff6600;">M</span></strong>（其中<strong><span style="color: #0000ff;">S</span></strong>是size，<strong><span style="color: #ff6600;">M</span></strong>是memory_semantic，例如__TBB_CompareAndSwap<span style="color: #0000ff;">4</span><span style="color: #ff6600;">acquire</span>）等方法。如果这些方法没有被定义的话，tbb_machine.h中会用__TBB_full_fence语义的版本重定义之。</p>
<p>atomic_rep: 对长度为[2, 4, 8]字节的类型，都要求对齐；即加入了一些编译器属性。</p>
<p>template struct atomic_traits;<br />
包括compare_and_swap, fetch_and_add, fetch_and_store等几个基本的方法。</p>
<p>atomic_impl实际上是对atomic_rep和atomic_traits的一个包装。而atomic模板从atomic_impl中派生得到的，对指针类型来说，是从atomic_impl_with_arithmetic中派生的（void *除外），以对指针的移动操作（例如++, &#8211;）进行memory barrier的保护。而atomic_impl_with_arithmetic也是从atomic_impl中派生的。相比atomic_impl，atomic对赋值操作operator=加入了fence的保护。</p>
<h1>tbb::blocked_range</h1>
<p>包括1维、2维、3维的实现。模板参数是iterator类型。表示一个半闭半开的区间，[my_begin, my_end)。当区间的size&lt;=my_grainsize时，区间就不可再分了。其中一个构造函数，可以将当前的range（*this）分为两半，新构造的range是后一半，旧的range被修改为前一半。</p>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/05/tbb-study-notes-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>黄山游小记</title>
		<link>http://yongsun.me/2010/05/%e9%bb%84%e5%b1%b1%e6%b8%b8%e5%b0%8f%e8%ae%b0/</link>
		<comments>http://yongsun.me/2010/05/%e9%bb%84%e5%b1%b1%e6%b8%b8%e5%b0%8f%e8%ae%b0/#comments</comments>
		<pubDate>Wed, 26 May 2010 16:21:13 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[游记]]></category>
		<category><![CDATA[黄山]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1430</guid>
		<description><![CDATA[跟随老婆单位同事组织的黄山游，4天3夜，加来去两晚的卧铺。 周五夜里的火车，硬卧上铺，空调风力太足，吹得我头痛不已。龟缩在被子里，蒙头浅睡了一夜。周六早起到合肥，有小雨，很冷。用罢早餐，乘事先联络好的旅游巴士，出合肥奔黄山方向。至汤口用午饭，然后驱车到西递参观。西递的很多牌楼和古籍，在文革时被破坏的很严重 &#8230; 傍晚到宏村入住在农家，吃农家菜。住宿条件很幽静，有热水可洗澡 &#8230; 第二天早起参观宏村，已经有了在西递屋檐累累的熏染，宏村的阁楼不再那么令人兴奋，但风景仍然十分迷人。 短短2小时之后，乘车去黄山。至黄山，乘中转巴士，到紫光阁。我们这一队老弱病残的同学，坐缆车上山。然后循大众路线至白云宾馆入住。中途路过迎客松，有点失望。且山中雾气弥漫，只偶尔露了几片蓝天。不过宾馆的条件比预期好得多。夜里各路人马汇合于宾馆，研讨分组路线，我和老婆第二天去挑战一个比较有难度的路线。晚上观摩了两局三国杀 &#8230; 第三天经光明顶，去北海看云海。8点钟至光明顶时，远眺云海很是壮观。遗憾的是，约1小时后，到达最佳观赏地，猴子观海时，已经消散了大半，很是遗憾。然后经排云亭，下西海大峡谷。经过4个小时的停停走走，终于回到了白云宾馆。因体力不支，没有继续随队去丹霞峰去看日落。晚上玩了两把三国杀。和另一队人马，相约隔天早起去看日出 &#8230; 第四天3:45起床，4点多一些到达光明顶时，观赏日出的各个据点已经人满为患了。辗转爬上悬崖边上的一大块岩石，脚下即是深渊。我爬上去之后，本已显得拥挤的岩顶，陆续又爬上来4个人，其中包括3位女士和一个老外。大家为了拍摄日出，真的是置生死于度外了。本来还想再去北海看云海，不过从光明顶看过去，当天是不会有云海现身了。于是回宾馆睡了个回笼觉。早上9点多和老婆再次经光明顶，至云古索道下山。中午随便在景区外吃了点饭，然后回合肥。到合肥吃了顿丰盛的晚饭，然后乘夜里的火车返京。 第五天早起到京，回到家洗了个澡，然后就去单位上班了 &#8230;]]></description>
			<content:encoded><![CDATA[<p>跟随老婆单位同事组织的黄山游，4天3夜，加来去两晚的卧铺。</p>
<p>周五夜里的火车，硬卧上铺，空调风力太足，吹得我头痛不已。龟缩在被子里，蒙头浅睡了一夜。周六早起到合肥，有小雨，很冷。用罢早餐，乘事先联络好的旅游巴士，出合肥奔黄山方向。至汤口用午饭，然后驱车到西递参观。西递的很多牌楼和古籍，在文革时被破坏的很严重 &#8230; 傍晚到宏村入住在农家，吃农家菜。住宿条件很幽静，有热水可洗澡 &#8230;</p>
<p>第二天早起参观宏村，已经有了在西递屋檐累累的熏染，宏村的阁楼不再那么令人兴奋，但风景仍然十分迷人。</p>
<p style="text-align: center;"><a href="http://www.flickr.com/photos/yong_sun/4647374412/sizes/l/"><img class="aligncenter" src="http://farm5.static.flickr.com/4068/4647374412_6e9fb8f0f8.jpg" alt="" width="500" height="189" /></a></p>
<p style="text-align: center;">
<p>短短2小时之后，乘车去黄山。至黄山，乘中转巴士，到紫光阁。我们这一队老弱病残的同学，坐缆车上山。然后循大众路线至白云宾馆入住。中途路过迎客松，有点失望。且山中雾气弥漫，只偶尔露了几片蓝天。不过宾馆的条件比预期好得多。夜里各路人马汇合于宾馆，研讨分组路线，我和老婆第二天去挑战一个比较有难度的路线。晚上观摩了两局三国杀 &#8230;</p>
<p>第三天经光明顶，去北海看云海。8点钟至光明顶时，远眺云海很是壮观。遗憾的是，约1小时后，到达最佳观赏地，猴子观海时，已经消散了大半，很是遗憾。然后经排云亭，下西海大峡谷。经过4个小时的停停走走，终于回到了白云宾馆。因体力不支，没有继续随队去丹霞峰去看日落。晚上玩了两把三国杀。和另一队人马，相约隔天早起去看日出 &#8230;</p>
<p>第四天3:45起床，4点多一些到达光明顶时，观赏日出的各个据点已经人满为患了。辗转爬上悬崖边上的一大块岩石，脚下即是深渊。我爬上去之后，本已显得拥挤的岩顶，陆续又爬上来4个人，其中包括3位女士和一个老外。大家为了拍摄日出，真的是置生死于度外了。本来还想再去北海看云海，不过从光明顶看过去，当天是不会有云海现身了。于是回宾馆睡了个回笼觉。早上9点多和老婆再次经光明顶，至云古索道下山。中午随便在景区外吃了点饭，然后回合肥。到合肥吃了顿丰盛的晚饭，然后乘夜里的火车返京。</p>
<p>第五天早起到京，回到家洗了个澡，然后就去单位上班了 &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/05/%e9%bb%84%e5%b1%b1%e6%b8%b8%e5%b0%8f%e8%ae%b0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>十年码工路——太阳下成长</title>
		<link>http://yongsun.me/2010/05/%e5%8d%81%e5%b9%b4%e7%a0%81%e5%b7%a5%e8%b7%af%e2%80%94%e2%80%94%e5%a4%aa%e9%98%b3%e4%b8%8b%e6%88%90%e9%95%bf/</link>
		<comments>http://yongsun.me/2010/05/%e5%8d%81%e5%b9%b4%e7%a0%81%e5%b7%a5%e8%b7%af%e2%80%94%e2%80%94%e5%a4%aa%e9%98%b3%e4%b8%8b%e6%88%90%e9%95%bf/#comments</comments>
		<pubDate>Fri, 14 May 2010 14:59:25 +0000</pubDate>
		<dc:creator>yongsun</dc:creator>
				<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://yongsun.me/?p=1391</guid>
		<description><![CDATA[2003年10月8日，国庆节后的第一个工作日，我来Sun中国工程研究院的北京国际化中心报到。我至今仍然十分感激当时的老板Scott，记得当初他面试我的时候，问我如果加入Sun有什么职业上的规划，我回答说“听闻Sun公司内部有transfer制度，员工可以在工作一定时间之后选择其他方向发展，如果有机会，我希望一两年后能transfer到浏览器组去做开发”。很感谢Scott，在听到我这么“二”的回答之后，还是给了我机会。 到Sun之后，第一个项目是接手Evolution的本地化和国际化，作为Evolution l10n/i18n项目的central engineer，要参与各种的项目会议，这对我来说的确是一个很大的挑战。我当初英文很差（当然现在也不好），很不习惯在电话里听别人说英文，口语的表达能力也很差。着实适应了一段时间。l10n/i18n的bug fixes有的可以很简单，有的则需要深入到程序内部，特别是有很多和输入、输出、DnD相关的问题，通常都很棘手。后来工作范围也扩展到了gnome上的l10n/i18n。为了管理测试用例和记录测试结果，学用Struts写了套很简陋的测试用例管理系统，不过因为其他site已经有同事写了一套类似的系统，而遭废弃。 04年6月份，有机会和同事（Gavin）到美国rotation两个月。我第一次坐飞机就是10多个小时的长途飞行，结果到了旧金山后发现无人接机。后来发现是同事把时差搞错了，告诉美国同事的接机时间，是当地的第二天。我们只好自己准备摸到公司租的公寓去。一路上先是坐Bart，然后坐Caltrain，好像当天Caltrain还因为是什么节日而免费，然后坐light-rail，最后坐bus，终于到了公寓附近。然后给国内的同事打电话，争取联系到接机的同事，恰好这位同事周末在单位加班，否则我们只有去办公室睡沙发了。我和Gavin都是穷苦孩子，过的很节省，都是自己做饭。一天两顿饭，晚上做好的菜，拨出一半留着明天中午带饭吃。两个月1000美元的补助（房租是公司付的），我买了100多美元的书，100多美元的化妆品（给老婆的），还老人家带了若干维生素，最后回国的时候，还剩了80美元的现金。美国的同事打趣说，500美元一个月的补助还是多了… 那段时间，我的同事张磊博士在独立开发一个基于统计语言模型的输入法，也就是今天的SunPinyin。我一下子就着了迷，找了很多NLP相关的论文和书来看。憧憬着有一天能够投入到这个输入法的开发中。后来，因为要弄一些自动测试的东西，又学了些shell脚本，还学了些python，以及pyrex，给python写扩展。业余时间，也翻译（或合译）了一些书，包括《Struts KickStart》，《Mastering JavaServer Faces》，《Agile Java》，《Programming Ruby》等一些技术书籍，对基于Web的企业应用开发也很有兴趣。我的一个最大的缺点就是兴趣太广，泛而不精。有时我很苦恼，有时又乐在其中，没办法了… 后来，Sun逐步削减了在JDS-Linux上的投入，将JDS上的一些开发都转移到Solaris上。我们和日本的一些同事，要负责将IIIMF的新版本（R12），从linux移植回solaris上。我还负责了简体中文、繁体中文、以及欧洲compose输入法的维护工作。这期间还代表公司参与了亚洲输入法标准的讨论和制定工作，结识了CJK许多输入法的开发者，例如James Su、Huang Peng、Wu Peng等等。我为日系和中系两路人马的沟通和交流做了一点点贡献。因为日本方面的主要负责人，Hideki Hiura，曾经是我们国际化部门的资深架构师，他是XIM协议的提出者之一，openi18n.org社区的奠基者。不幸的是，前不久得到他的噩耗，因病逝世了:( 同志们都要注意身体啊… 这个标准工作组最后同意开发一个全新的输入法平台，即imbus。但是由于种种原因，始终停滞不前。后来，我和Huang Peng一起提出了用python+dbus实现输入法平台的初步构想，也就是今天的iBus。很遗憾，我只是提了一个构想，贡献过一些很high-level的design，并没有贡献过什么代码。 后来，张磊同学去我们的宿敌M$做Bing去了 便将SunPinyin的开发和维护工作转交给了我。随着OpenSolaris的开源计划，SunPinyin也一并以CDDL协议开放给了社区。为了吸引更多的开发者加入我们，我写了一系列的blog，介绍SunPinyin内部的实现细节。我的blog也因而经常出现在blogs.sun.com访问量的前60名（尾部）。也因为在博客上的交流，结识了tchaik0v同学。他很热心的帮助我们将SunPinyin从IIIMF移植到了SCIM平台上，现在仍然是SunPinyin社区中最主力的开发人员之一。为了让Linux各发行版能更好的接纳SunPinyin，我又建议和推动了将SunPinyin改为CDDL+LGPLv2的双授权协议（这一协议也沿用至今）。 后来迷上了Apple，买了台MBP。MacOS自带的拼音输入法着实很难用。QIM是收费软件，FIT虽然免费，但也不是很满意，就想能不能把SunPinyin移植到Mac上。随着Leopard的发布，基于IMKit框架开发输入法变得比较轻便和容易了。我花了四天三晚，照着苹果官方的例子，对着obj-c/cocoa的简明教程，将SunPinyin初步移植到了Leopard上。很感谢我的老板，允许我干这么一件看起来和Sun的业务毫无关系的事情。实际上，我们的这个移植还是非常划算的。Mac的用户都是一群完美主义者，给我们提了大量的意见和建议，极大地鞭策和促进了SunPinyin的继续发展。我也因此结识了jjgod、Lin Zheming、chumsdock等许多好朋友。 因为SunPinyin-1.0架构上的一些局限，要实现一些新特性很困难，因此我就开始了2.0版本的开发。在开发过程中，也把同事Xue Wei给involve进来，帮助我实现了双拼切分和用户词典的功能。直到这时，我仍然时不时地需要去fix一些IIIMF的bug；有时还要做很多RE（Releasing Engineer）的工作；还有其他一些小的项目。这些琐碎的工作有时真得让我感到很沮丧。后来同事帮我做了一个统计，我在Sun的这近6年时间里，周均要fix 1.5个bug，大概是我们北京国际化中心这边入职时间相当的工程师里，最多的一个。 08年的金融危机，成了压在Sun身上的最后一根稻草。Sun被Oracle以74亿美金收购了。一轮又一轮的裁员，部门里的人事和结构的不断变更，HR的一些“作为”，以及对并购后工作方向上的不确定性，让我渐渐有了离开的念头。后来，汤森路透这边有一个机会，是用C++开发高并发的金融应用。我对并发编程一直很有兴趣，虽然很犹豫，最后还是接受了offer。我的老板和二线老板都希望我能留下来，至少等收购完成看一看再说。我的老板们对我都很nice，一直很支持我，如果还没有签offer，我想我真的会选择留下来… 无论从哪方面讲，Sun都是一家伟大的公司，公司的文化非常宽松和开放，给员工的自由度非常大，也非常鼓励员工的创新。我们部门可以全周在家办公，只需要周四到单位碰个面；不定期的有knowledge sharing的session，这个session可以讲任何大家有兴趣的topic，甚至包括摄影、装修、理财等和工作毫无关系的内容。这些都让我们部门成为一个充满家庭般温暖的、紧密团结的大家庭。如果不是因为收购的问题，我真的希望自己能在Sun做到退休… 2009年8月20日，在美国政府批准Oracle收购案的前一天，我从公司离职了。而到今天为止，Sun中国工程研究院还没有合并到Oracle中国研发部门。我所在的那个组，曾经10来个人的team，走得只剩下两个人了… 在Sun的近6年岁月里，我获益良多，这是我从业以来最开心的日子，我将永远铭记在心…]]></description>
			<content:encoded><![CDATA[<p>2003年10月8日，国庆节后的第一个工作日，我来Sun中国工程研究院的北京国际化中心报到。我至今仍然十分感激当时的老板Scott，记得当初他面试我的时候，问我如果加入Sun有什么职业上的规划，我回答说“听闻Sun公司内部有transfer制度，员工可以在工作一定时间之后选择其他方向发展，如果有机会，我希望一两年后能transfer到浏览器组去做开发”。很感谢Scott，在听到我这么“二”的回答之后，还是给了我机会。</p>
<p>到Sun之后，第一个项目是接手Evolution的本地化和国际化，作为Evolution l10n/i18n项目的central engineer，要参与各种的项目会议，这对我来说的确是一个很大的挑战。我当初英文很差（当然现在也不好），很不习惯在电话里听别人说英文，口语的表达能力也很差。着实适应了一段时间。l10n/i18n的bug fixes有的可以很简单，有的则需要深入到程序内部，特别是有很多和输入、输出、DnD相关的问题，通常都很棘手。后来工作范围也扩展到了gnome上的l10n/i18n。为了管理测试用例和记录测试结果，学用Struts写了套很简陋的测试用例管理系统，不过因为其他site已经有同事写了一套类似的系统，而遭废弃。</p>
<p>04年6月份，有机会和同事（Gavin）到美国rotation两个月。我第一次坐飞机就是10多个小时的长途飞行，结果到了旧金山后发现无人接机。后来发现是同事把时差搞错了，告诉美国同事的接机时间，是当地的第二天。我们只好自己准备摸到公司租的公寓去。一路上先是坐Bart，然后坐Caltrain，好像当天Caltrain还因为是什么节日而免费，然后坐light-rail，最后坐bus，终于到了公寓附近。然后给国内的同事打电话，争取联系到接机的同事，恰好这位同事周末在单位加班，否则我们只有去办公室睡沙发了。我和Gavin都是穷苦孩子，过的很节省，都是自己做饭。一天两顿饭，晚上做好的菜，拨出一半留着明天中午带饭吃。两个月1000美元的补助（房租是公司付的），我买了100多美元的书，100多美元的化妆品（给老婆的），还老人家带了若干维生素，最后回国的时候，还剩了80美元的现金。美国的同事打趣说，500美元一个月的补助还是多了…</p>
<p>那段时间，我的同事张磊博士在独立开发一个基于统计语言模型的输入法，也就是今天的SunPinyin。我一下子就着了迷，找了很多NLP相关的论文和书来看。憧憬着有一天能够投入到这个输入法的开发中。后来，因为要弄一些自动测试的东西，又学了些shell脚本，还学了些python，以及pyrex，给python写扩展。业余时间，也翻译（或合译）了一些书，包括《Struts KickStart》，《Mastering JavaServer Faces》，《Agile Java》，《Programming Ruby》等一些技术书籍，对基于Web的企业应用开发也很有兴趣。我的一个最大的缺点就是兴趣太广，泛而不精。有时我很苦恼，有时又乐在其中，没办法了…</p>
<p>后来，Sun逐步削减了在JDS-Linux上的投入，将JDS上的一些开发都转移到Solaris上。我们和日本的一些同事，要负责将IIIMF的新版本（R12），从linux移植回solaris上。我还负责了简体中文、繁体中文、以及欧洲compose输入法的维护工作。这期间还代表公司参与了亚洲输入法标准的讨论和制定工作，结识了CJK许多输入法的开发者，例如James Su、Huang Peng、Wu Peng等等。我为日系和中系两路人马的沟通和交流做了一点点贡献。因为日本方面的主要负责人，Hideki Hiura，曾经是我们国际化部门的资深架构师，他是XIM协议的提出者之一，openi18n.org社区的奠基者。不幸的是，前不久得到他的噩耗，因病逝世了:( 同志们都要注意身体啊…</p>
<p>这个标准工作组最后同意开发一个全新的输入法平台，即imbus。但是由于种种原因，始终停滞不前。后来，我和Huang Peng一起提出了用python+dbus实现输入法平台的初步构想，也就是今天的iBus。很遗憾，我只是提了一个构想，贡献过一些很high-level的design，并没有贡献过什么代码。</p>
<p>后来，张磊同学去我们的宿敌M$做Bing去了 <img src='http://yongsun.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  便将SunPinyin的开发和维护工作转交给了我。随着OpenSolaris的开源计划，SunPinyin也一并以CDDL协议开放给了社区。为了吸引更多的开发者加入我们，我写了一系列的blog，介绍SunPinyin内部的实现细节。我的blog也因而经常出现在blogs.sun.com访问量的前60名（尾部）。也因为在博客上的交流，结识了<a href="http://twitter.com/tchaik0v">tchaik0v</a>同学。他很热心的帮助我们将SunPinyin从IIIMF移植到了SCIM平台上，现在仍然是SunPinyin社区中最主力的开发人员之一。为了让Linux各发行版能更好的接纳SunPinyin，我又建议和推动了将SunPinyin改为CDDL+LGPLv2的双授权协议（这一协议也沿用至今）。</p>
<p>后来迷上了Apple，买了台MBP。MacOS自带的拼音输入法着实很难用。QIM是收费软件，FIT虽然免费，但也不是很满意，就想能不能把SunPinyin移植到Mac上。随着Leopard的发布，基于IMKit框架开发输入法变得比较轻便和容易了。我花了四天三晚，照着苹果官方的例子，对着obj-c/cocoa的简明教程，将SunPinyin初步移植到了Leopard上。很感谢我的老板，允许我干这么一件看起来和Sun的业务毫无关系的事情。实际上，我们的这个移植还是非常划算的。Mac的用户都是一群完美主义者，给我们提了大量的意见和建议，极大地鞭策和促进了SunPinyin的继续发展。我也因此结识了<a href="http://twitter.com/jjgod">jjgod</a>、<a href="http://twitter.com/linzheming">Lin Zheming</a>、<a href="http://twitter.com/chumsdock">chumsdock</a>等许多好朋友。</p>
<p>因为SunPinyin-1.0架构上的一些局限，要实现一些新特性很困难，因此我就开始了2.0版本的开发。在开发过程中，也把同事<a href="http://twitter.com/billxue">Xue Wei</a>给involve进来，帮助我实现了双拼切分和用户词典的功能。直到这时，我仍然时不时地需要去fix一些IIIMF的bug；有时还要做很多RE（Releasing Engineer）的工作；还有其他一些小的项目。这些琐碎的工作有时真得让我感到很沮丧。后来同事帮我做了一个统计，我在Sun的这近6年时间里，周均要fix 1.5个bug，大概是我们北京国际化中心这边入职时间相当的工程师里，最多的一个。</p>
<p>08年的金融危机，成了压在Sun身上的最后一根稻草。Sun被Oracle以74亿美金收购了。一轮又一轮的裁员，部门里的人事和结构的不断变更，HR的一些“作为”，以及对并购后工作方向上的不确定性，让我渐渐有了离开的念头。后来，汤森路透这边有一个机会，是用C++开发高并发的金融应用。我对并发编程一直很有兴趣，虽然很犹豫，最后还是接受了offer。我的老板和二线老板都希望我能留下来，至少等收购完成看一看再说。我的老板们对我都很nice，一直很支持我，如果还没有签offer，我想我真的会选择留下来…</p>
<p>无论从哪方面讲，Sun都是一家伟大的公司，公司的文化非常宽松和开放，给员工的自由度非常大，也非常鼓励员工的创新。我们部门可以全周在家办公，只需要周四到单位碰个面；不定期的有knowledge sharing的session，这个session可以讲任何大家有兴趣的topic，甚至包括摄影、装修、理财等和工作毫无关系的内容。这些都让我们部门成为一个充满家庭般温暖的、紧密团结的大家庭。如果不是因为收购的问题，我真的希望自己能在Sun做到退休…</p>
<p>2009年8月20日，在美国政府批准Oracle收购案的前一天，我从公司离职了。而到今天为止，Sun中国工程研究院还没有合并到Oracle中国研发部门。我所在的那个组，曾经10来个人的team，走得只剩下两个人了…</p>
<p>在Sun的近6年岁月里，我获益良多，这是我从业以来最开心的日子，我将永远铭记在心…</p>
]]></content:encoded>
			<wfw:commentRss>http://yongsun.me/2010/05/%e5%8d%81%e5%b9%b4%e7%a0%81%e5%b7%a5%e8%b7%af%e2%80%94%e2%80%94%e5%a4%aa%e9%98%b3%e4%b8%8b%e6%88%90%e9%95%bf/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>
