<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Static Oneplus</title>
  <subtitle>不可控制论</subtitle>
  <id>http://yjliu.net/blog</id>
  <link href="http://yjliu.net/blog"/>
  <link href="http://yjliu.net/feed.xml" rel="self"/>
  <updated>2015-05-20T16:00:00Z</updated>
  <author>
    <name>Oneplus</name>
  </author>
  <entry>
    <title>New neural parser added to LTP</title>
    <link rel="alternate" href="http://yjliu.net/blog/2015/05/21/new-ltp-release.html"/>
    <id>http://yjliu.net/blog/2015/05/21/new-ltp-release.html</id>
    <published>2015-05-20T16:00:00Z</published>
    <updated>2015-05-25T15:36:25+08:00</updated>
    <author>
      <name>Article Author</name>
    </author>
    <content type="html">&lt;p&gt;[&lt;a href="https://github.com/HIT-SCIR/ltp/releases/tag/v3.3.0"&gt;Github&lt;/a&gt;]
[&lt;a href="http://pan.baidu.com/share/link?shareid=1988562907&amp;amp;amp;uk=2738088569#path=%252Fltp-models%252F3.3.0"&gt;Pre-trained Model&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;We recently added a new dependency parser to LTP.
This parser is a transiton-based neural network parser, which mainly based on Chen and Manning (2014).
Besides the parser originally described in their work, additional features are also incorporated in our parser, including global feature (Zhang and Nivre, 2011), word cluster and dynamic oracle (Goldberg et. al. 2014).
Dr. Jiang Guo developed the prototype for this parser in his &lt;em&gt;ACL2015&lt;/em&gt; work.&lt;/p&gt;

&lt;p&gt;For quick summary, our new parser’s main features includes&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fast linear parsing time: over 8,000 tokens/second.&lt;/li&gt;
  &lt;li&gt;High parsing accuracy: 85.24 (UAS) on CTB5&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and the key techniques includes&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Linear time transition-based parsing.&lt;/li&gt;
  &lt;li&gt;Neural network classifier with cubic active function&lt;/li&gt;
  &lt;li&gt;Supporting clustering features and global features&lt;/li&gt;
  &lt;li&gt;Supporting learning from dynamic oracle&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="word-cluster"&gt;Word Cluster&lt;/h3&gt;

&lt;p&gt;Word cluster can be the most reliable feature acrossing the syntactic tasks, including POS tagging, NER and parsing.
Thus, the performance improvement we gain from word cluster is as expected.
In our system, word cluster is added to as another ‘POS tag’.&lt;/p&gt;

&lt;h3 id="global-feature"&gt;Global Feature&lt;/h3&gt;

&lt;p&gt;Zhang and Nivre (2012) study the problem of interaction between searching and learning. Their work can be summarized as&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;local learning + greedy search: [good]&lt;/li&gt;
  &lt;li&gt;local learning + beam search: [bad]&lt;/li&gt;
  &lt;li&gt;global learning + greedy search: [bad]&lt;/li&gt;
  &lt;li&gt;global learning + beam search: [good]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They also say that&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;local learning + global features: [bad]&lt;/li&gt;
  &lt;li&gt;global learning + global features: [good]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also found that global features contribute nothing if they are added to the parser standalone.
But we found that when coupled with word cluster, the global feature can further help.
Thus, this feature is add in our released version.&lt;/p&gt;

&lt;h3 id="dynamic-oracle"&gt;Dynamic Oracle&lt;/h3&gt;

&lt;p&gt;Dynamic oracle is another reliable stuff!
On the NLTK’s issues list, Dr. Honnibal (author of spaCy) quoted that&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Second, when you train the parser, you parser, you should really use the Goldberg and Nivre (2012) “dynamic oracle” strategy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We also found dynamic oracle works great on Chinese dataset.
The detailed result will be presented in experiment section.&lt;/p&gt;

&lt;h3 id="experiment"&gt;Experiment&lt;/h3&gt;

&lt;p&gt;We report our parser’s performance on Chinese treebank 5 and Chinese dependency treebank.
Parsing accuray is evaluated using UAS/LAS.
We also compare our result with the our old LTP parser and the other state-of-the-art parsers.&lt;/p&gt;

&lt;h4 id="ctb5-experiment"&gt;CTB5 experiment&lt;/h4&gt;

&lt;p&gt;CTB5 data is splited according to Zhang and Clark (2008), with 16,091 for training, 1,910 for testing and 803 for development.
Word embedding trained on Gigawords xinhua news with word2vec is used as initialization embedding.
Brown clustering result with 1000 clusters on the same data are also used in our experiment.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Parser&lt;/th&gt;
      &lt;th&gt;Dev.UAS&lt;/th&gt;
      &lt;th&gt;Dev.LAS&lt;/th&gt;
      &lt;th&gt;Test.UAS&lt;/th&gt;
      &lt;th&gt;Test.LAS&lt;/th&gt;
      &lt;th&gt;Test Speed(tokens/sec.)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ZPar (b=64)&lt;/td&gt;
      &lt;td&gt;85.15&lt;/td&gt;
      &lt;td&gt;85.45&lt;/td&gt;
      &lt;td&gt;85.82&lt;/td&gt;
      &lt;td&gt;84.54&lt;/td&gt;
      &lt;td&gt;(about-) 700&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LTP (o2sib)&lt;/td&gt;
      &lt;td&gt;84.46&lt;/td&gt;
      &lt;td&gt;82.96&lt;/td&gt;
      &lt;td&gt;84.05&lt;/td&gt;
      &lt;td&gt;82.62&lt;/td&gt;
      &lt;td&gt;40.99(?)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN (e=50,h=200)&lt;/td&gt;
      &lt;td&gt;82.87&lt;/td&gt;
      &lt;td&gt;81.13&lt;/td&gt;
      &lt;td&gt;83.22&lt;/td&gt;
      &lt;td&gt;81.68&lt;/td&gt;
      &lt;td&gt;16737.41&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN-nondet(e=50,h=200)&lt;/td&gt;
      &lt;td&gt;83.48&lt;/td&gt;
      &lt;td&gt;81.75&lt;/td&gt;
      &lt;td&gt;83.95&lt;/td&gt;
      &lt;td&gt;82.40&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN-explore(e=50,h=200)&lt;/td&gt;
      &lt;td&gt;84.42&lt;/td&gt;
      &lt;td&gt;82.68&lt;/td&gt;
      &lt;td&gt;84.44&lt;/td&gt;
      &lt;td&gt;82.70&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN-explore+glob.feat(e=50,h=200)&lt;/td&gt;
      &lt;td&gt;84.48&lt;/td&gt;
      &lt;td&gt;82.79&lt;/td&gt;
      &lt;td&gt;84.74&lt;/td&gt;
      &lt;td&gt;83.02&lt;/td&gt;
      &lt;td&gt;14627.79&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN-explore+cluster(e=50,h=200)&lt;/td&gt;
      &lt;td&gt;85.08&lt;/td&gt;
      &lt;td&gt;83.26&lt;/td&gt;
      &lt;td&gt;84.98&lt;/td&gt;
      &lt;td&gt;83.28&lt;/td&gt;
      &lt;td&gt;9734.88&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN-explore+glob.feat+cluster(e=50,h=200)&lt;/td&gt;
      &lt;td&gt;85.16&lt;/td&gt;
      &lt;td&gt;83.54&lt;/td&gt;
      &lt;td&gt;85.24&lt;/td&gt;
      &lt;td&gt;83.61&lt;/td&gt;
      &lt;td&gt;9325.72&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id="cdt-experiment"&gt;CDT experiment&lt;/h4&gt;

&lt;p&gt;Suggested data split is used in CDT experiment.
Embedding and cluster settings are almost identical to the CTB5 experiment except that data are segmented with a PKU standard segmentor.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Parser&lt;/th&gt;
      &lt;th&gt;Dev.UAS&lt;/th&gt;
      &lt;th&gt;Dev.LAS&lt;/th&gt;
      &lt;th&gt;Test.UAS&lt;/th&gt;
      &lt;th&gt;Test.LAS&lt;/th&gt;
      &lt;th&gt;Test Speed(tokens/sec.)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ZPar (b=64)&lt;/td&gt;
      &lt;td&gt;86.43&lt;/td&gt;
      &lt;td&gt;83.68&lt;/td&gt;
      &lt;td&gt;85.48&lt;/td&gt;
      &lt;td&gt;82.41&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LTP (o2sib)&lt;/td&gt;
      &lt;td&gt;84.95&lt;/td&gt;
      &lt;td&gt;82.09&lt;/td&gt;
      &lt;td&gt;83.99&lt;/td&gt;
      &lt;td&gt;81.31&lt;/td&gt;
      &lt;td&gt;263.89&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN (e=50,h=400)&lt;/td&gt;
      &lt;td&gt;84.33&lt;/td&gt;
      &lt;td&gt;81.57&lt;/td&gt;
      &lt;td&gt;83.04&lt;/td&gt;
      &lt;td&gt;80.01&lt;/td&gt;
      &lt;td&gt;11478.48&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN-explore(e=50,h=400)&lt;/td&gt;
      &lt;td&gt;85.02&lt;/td&gt;
      &lt;td&gt;82.41&lt;/td&gt;
      &lt;td&gt;83.74&lt;/td&gt;
      &lt;td&gt;80.81&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN-explore+glob.feat(e=50,h=400)&lt;/td&gt;
      &lt;td&gt;84.81&lt;/td&gt;
      &lt;td&gt;82.23&lt;/td&gt;
      &lt;td&gt;83.56&lt;/td&gt;
      &lt;td&gt;80.65&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN-explore+cluster(e=50,h=400)&lt;/td&gt;
      &lt;td&gt;85.82&lt;/td&gt;
      &lt;td&gt;83.25&lt;/td&gt;
      &lt;td&gt;83.49&lt;/td&gt;
      &lt;td&gt;80.60&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;NN-explore+glob.feat+cluster(e=50,h=400)&lt;/td&gt;
      &lt;td&gt;85.80&lt;/td&gt;
      &lt;td&gt;83.19&lt;/td&gt;
      &lt;td&gt;84.11&lt;/td&gt;
      &lt;td&gt;81.17&lt;/td&gt;
      &lt;td&gt;8448.45&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Generally speaking, the dynamic oracle shows to improve parsing accuracy on both dataset.
What’s more, brown cluster is also a great feature to boost up the score.&lt;/p&gt;

&lt;h3 id="in-a-way-to-kill-old-people"&gt;“In a way to kill old people”&lt;/h3&gt;

&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"&gt;&lt;/script&gt;

&lt;p&gt;We can see the parsing accuracy and speed benchmark with our the old LTP parser in the following chart.&lt;/p&gt;

&lt;canvas id="speed" width="200" height="300"&gt;&lt;/canvas&gt;
&lt;canvas id="accuracy" width="200" height="300"&gt;&lt;/canvas&gt;

&lt;script&gt;
var spd_dat = {
    labels: ["old parser", "new parser",],
    datasets: [
    {
        label: "parsing speed",
        fillColor: "rgba(220,220,220,0.5)",
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        data: [263.89, 8448.45]
    }]
};
var acc_dat = {
    labels: ["old parser", "new parser",],
    datasets: [
    {
        label: "parsing accuracy",
        fillColor: "rgba(220,220,220,0.5)",
        strokeColor: "rgba(220,220,220,0.8)",
        highlightFill: "rgba(220,220,220,0.75)",
        highlightStroke: "rgba(220,220,220,1)",
        data: [83.99, 84.11]
    }]
};

var spd_ctx= document.getElementById("speed").getContext("2d");
new Chart(spd_ctx).Bar(spd_dat, {barShowStroke: false});
var acc_ctx= document.getElementById("accuracy").getContext("2d");
new Chart(acc_ctx).Bar(acc_dat, {barShowStroke: false});
&lt;/script&gt;

&lt;p&gt;In a way to kill old people, as the phrase is.&lt;/p&gt;

&lt;h3 id="reference"&gt;Reference&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Danqi Chen and Christopher Manning, 2014, A Fast and Accurate Dependency Parser using Neural Networks, In Proc. &lt;em&gt;EMNLP2014&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Yue Zhang and Joakim Nivre, 2011, Transition-based Dependency Parsing with Rich Non-local Features, In Proc &lt;em&gt;ACL2011&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Yoav Goldberg, Francesco Sartorioand Giorgio Satta, 2014, A Tabular Method for Dynamic Oracles in Transition-Based Parsing, In &lt;em&gt;TACL2014&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Jiang Guo, Wanxiang Che, David Yarowsky, Haifeng Wang and Ting Liu, 2015, Cross-lingual Dependency Parsing Based on Distributed Representations, (to apper) In Proc &lt;em&gt;ACL2015&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Yue Zhang and Joakim Nivre, 2012, Analyzing the Effect of Global Learning and Beam-Search on Transition-Based Dependency Parsing, In Proc &lt;em&gt;COLING2012&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Yue Zhang and Stephen Clark, A Tale of Two Parsers: Investigating and Combining Graph-based and Transition-based Dependency Parsing, In Proc &lt;em&gt;ACL2008&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;style&gt;
table{ border-collapse: collapse; border-spacing: 0; border:2px solid #ff0000; width: 100%; }
th{ border:2px solid #000000; }
td{ border:1px solid #000000; }
&lt;/style&gt;

</content>
  </entry>
  <entry>
    <title>ZGen v0.2.0 Released</title>
    <link rel="alternate" href="http://yjliu.net/blog/2015/03/29/zgen-release.html"/>
    <id>http://yjliu.net/blog/2015/03/29/zgen-release.html</id>
    <published>2015-03-28T16:00:00Z</published>
    <updated>2015-05-21T09:46:55+08:00</updated>
    <author>
      <name>Article Author</name>
    </author>
    <content type="html">&lt;p&gt;[&lt;a href="http://sourceforge.net/projects/zgen/"&gt;Sourceforge Project Home&lt;/a&gt;]
[&lt;a href="https://github.com/Oneplus/ZGen"&gt;Github Mirror&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;I’ve been working on the ZGen project since Sept. the last year. It’s a linearization system that constructs natural language
sentences from bags of words, given optional input syntactic constraints. Depending on the amount of input constraints, ZGen
can perform free ordering, partial tree linearization and full tree linearization. It’s the system I used in my NAACL2015 
paper: &lt;em&gt;Transition-Based Syntactic Linearization&lt;/em&gt;. Any feedback is welcome!&lt;/p&gt;

&lt;p&gt;Sentence generation is an interesting but less studied topic, partly because the complexity of the generation system. The
current version of ZGen can never make up a generation system, but hopefully it can perform generation from logic form or
key words or a sentence topic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ZGen&lt;/strong&gt; is named after the &lt;em&gt;ZPar&lt;/em&gt; project from my supervisor and corporator Dr. Yue Zhang. He must be marching on the road of
&lt;em&gt;ZNLP&lt;/em&gt; :-)&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>A benchmark on mapping few keys</title>
    <link rel="alternate" href="http://yjliu.net/blog/2015/03/10/benchmark-on-mapping-few-keys.html"/>
    <id>http://yjliu.net/blog/2015/03/10/benchmark-on-mapping-few-keys.html</id>
    <published>2015-03-09T16:00:00Z</published>
    <updated>2015-03-10T19:36:56+08:00</updated>
    <author>
      <name>Article Author</name>
    </author>
    <content type="html">&lt;p&gt;Recently, I’ve worked on optimizing my transition-based parser and came across such situation:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I need an associated, or key-value, structure to store the cached scored for each transition action at a certain state.
In practice, the number of transition actions is relatively small (less than 100), so I became curious about the best associated data structure for small set of keys.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Previous posts on such performance benchmark mainly focus on the comparsion of different hash maps on large scale, like &lt;a href="http://incise.org/hash-table-benchmarks.html"&gt;this one&lt;/a&gt;.
This post differs from theirs by setting the number of keys to a small number.
Time consumption on &lt;em&gt;random insertion&lt;/em&gt;, &lt;em&gt;ordered insertion&lt;/em&gt;, &lt;em&gt;random retrieve&lt;/em&gt; and &lt;em&gt;ordered retrieve&lt;/em&gt; is evaluated.
I didn’t give a try on the &lt;em&gt;delete&lt;/em&gt; operation cause there is no such operation in my problems.&lt;/p&gt;

&lt;p&gt;Three types of mapping facilities are adopted in this posts.
They are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Tree&lt;/strong&gt;: &lt;code&gt;std::map&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Ordered List&lt;/strong&gt;: &lt;code&gt;boost::container::flat_map&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Hashtable&lt;/strong&gt;: &lt;code&gt;std::unordered_map&lt;/code&gt;, &lt;code&gt;boost::unordered_map&lt;/code&gt;, &lt;code&gt;google::sparse_hash_map&lt;/code&gt;, &lt;code&gt;google::dense_hash_map&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;std::map&lt;/code&gt; is a several-time loser in previous benchmark because of the O(log n) time complexity.
I choose the &lt;code&gt;std::map&lt;/code&gt; and hope it can win a round in this special situation.
&lt;code&gt;boost::container::flat_map&lt;/code&gt; is suggested by &lt;a href="http://stackoverflow.com/questions/15625225/map-vs-unordered-map-for-few-elements"&gt;this StackOverflow question&lt;/a&gt;.
It seems the key are ordered and stored in a list in &lt;code&gt;boost::container::flat_map&lt;/code&gt;, rather than a tree like the &lt;code&gt;std::map&lt;/code&gt; does.
Expectingly, this data structure should have some nice memory allocation feature compared with the &lt;code&gt;std::map&lt;/code&gt;.
The &lt;strong&gt;Hashtable&lt;/strong&gt; group is actually my old friends and I used &lt;code&gt;google::dense_hash_map&lt;/code&gt; and &lt;code&gt;std::unordered_map&lt;/code&gt; a lot.&lt;/p&gt;

&lt;h3 id="results"&gt;Results&lt;/h3&gt;

&lt;p&gt;All the experiments are conducted on a Xeon(R) CPU E5-2620 @ 2.00GHz server.
My GCC is a new-version one, the 4.8.2.
The code used in this benchmark can be found at &lt;a href="https://gist.github.com/Oneplus/95aca812db7df06db4a6"&gt;this gist&lt;/a&gt;.
&lt;code&gt;-O3&lt;/code&gt; optimizing level is configured in compling the code.&lt;/p&gt;

&lt;p&gt;The benchmark results are shown below.&lt;/p&gt;

&lt;script language="javascript" type="text/javascript" src="http://flot.googlecode.com/svn/trunk/jquery.js"&gt;&lt;/script&gt;

&lt;script language="javascript" type="text/javascript" src="http://flot.googlecode.com/svn/trunk/jquery.flot.js"&gt;&lt;/script&gt;

&lt;script&gt;
series_settings = {
    lines: { show: true },
    points: { show: true }
};
grid_settings = { tickColor: '#ddd' };
xaxis_settings = {
    tickSize: 5,
    tickFormatter: function(num, obj) { return num; }
};
yaxis_runtime_settings = {
    tickSize: 3,
    tickFormatter: function(num, obj) { return num + ' sec.'; }
};
legend_settings = {
    position: 'nw',
    backgroundOpacity: 0
};
runtime_settings = {
    series: series_settings,
    grid: grid_settings,
    xaxis: xaxis_settings,
    yaxis: yaxis_runtime_settings,
    legend: legend_settings
};

chart_data = {"insert_ordered": [{"data": [[7, 0.409322], [10, 0.585166], [22, 1.341716], [34, 2.139042], [44, 3.038083], [59, 4.370022], [68, 4.935407], [77, 5.307655], [84, 5.844386], [94, 6.582139], [108, 8.13809], [117, 8.708292], [128, 9.185893]], "label": "GCC 4.8.2 std::map"}, {"data": [[7, 0.519962], [10, 0.759663], [22, 1.858168], [34, 3.708597], [44, 4.137573], [59, 7.066421], [68, 7.991669], [77, 8.343582], [84, 7.938728], [94, 8.793034], [108, 13.404046], [117, 13.88253], [128, 14.58537]], "label": "GCC 4.8.2 std::unordered_map"}, {"data": [[7, 0.550035], [10, 1.051826], [22, 2.03427], [34, 5.646686], [44, 6.974083], [59, 14.161613], [68, 15.367167], [77, 16.903076], [84, 16.48261], [94, 21.557487], [108, 38.543933], [117, 41.327302], [128, 39.764304]], "label": "Google sparsehash 2.0 sparse_hash_map"}, {"data": [[7, 0.164327], [10, 0.196777], [22, 0.672963], [34, 1.394658], [44, 1.434241], [59, 1.797652], [68, 2.955158], [77, 2.562484], [84, 2.776381], [94, 2.985307], [108, 3.199112], [117, 3.242178], [128, 3.226103]], "label": "Google sparsehash 2.0 dense_hash_map"}, {"data": [[7, 0.633299], [10, 0.889551], [22, 2.800967], [34, 4.726608], [44, 5.401382], [59, 8.81247], [68, 9.751447], [77, 9.189723], [84, 10.183168], [94, 12.195744], [108, 15.87413], [117, 15.845215], [128, 16.748076]], "label": "Boost 1.57 unordered_map"}, {"data": [[7, 0.439004], [10, 0.54523], [22, 0.648596], [34, 1.187385], [44, 1.370228], [59, 1.634742], [68, 2.006426], [77, 2.029157], [84, 2.198808], [94, 2.398985], [108, 2.659591], [117, 2.662692], [128, 2.822689]], "label": "Boost 1.57 container/flat_map"}], "query_ordered": [{"data": [[7, 0.442178], [10, 0.504482], [22, 0.637969], [34, 0.661629], [44, 0.758225], [59, 0.828777], [68, 0.842935], [77, 0.842343], [84, 0.834386], [94, 0.854975], [108, 0.918758], [117, 0.885608], [128, 0.889101]], "label": "GCC 4.8.2 std::map"}, {"data": [[7, 2.992673], [10, 3.446545], [22, 3.726248], [34, 3.118768], [44, 3.825269], [59, 3.088826], [68, 3.323022], [77, 3.39234], [84, 3.532552], [94, 3.777222], [108, 2.875106], [117, 2.94179], [128, 3.004405]], "label": "GCC 4.8.2 std::unordered_map"}, {"data": [[7, 1.406637], [10, 1.907112], [22, 3.981396], [34, 3.729011], [44, 5.419971], [59, 3.247684], [68, 3.848389], [77, 4.635114], [84, 4.906134], [94, 5.902078], [108, 3.05959], [117, 3.217729], [128, 3.553654]], "label": "Google sparsehash 2.0 sparse_hash_map"}, {"data": [[7, 0.71078], [10, 1.003725], [22, 1.015675], [34, 0.885142], [44, 1.093953], [59, 1.473621], [68, 0.883818], [77, 0.965263], [84, 0.941491], [94, 1.194417], [108, 1.392917], [117, 1.469674], [128, 1.496883]], "label": "Google sparsehash 2.0 dense_hash_map"}, {"data": [[7, 2.763566], [10, 3.279529], [22, 3.674283], [34, 3.613969], [44, 3.944727], [59, 3.576254], [68, 3.843012], [77, 3.70055], [84, 3.951947], [94, 4.445336], [108, 3.424645], [117, 3.374889], [128, 3.504379]], "label": "Boost 1.57 unordered_map"}, {"data": [[7, 0.578214], [10, 0.640305], [22, 0.796682], [34, 0.940796], [44, 1.019577], [59, 1.089206], [68, 1.095279], [77, 1.069663], [84, 1.071094], [94, 1.17977], [108, 1.184879], [117, 1.158933], [128, 1.239591]], "label": "Boost 1.57 container/flat_map"}], "insert_random": [{"data": [[7, 0.453461], [10, 0.636787], [22, 1.431945], [34, 2.409063], [44, 3.279204], [59, 4.396479], [68, 5.259939], [77, 5.70331], [84, 6.175281], [94, 6.765964], [108, 8.568328], [117, 9.25607], [128, 9.453532]], "label": "GCC 4.8.2 std::map"}, {"data": [[7, 0.520997], [10, 0.795826], [22, 1.849433], [34, 3.595913], [44, 4.257769], [59, 6.986665], [68, 7.913297], [77, 8.298659], [84, 7.833349], [94, 8.508522], [108, 12.582747], [117, 13.721128], [128, 14.607924]], "label": "GCC 4.8.2 std::unordered_map"}, {"data": [[7, 0.542842], [10, 1.048864], [22, 2.033791], [34, 5.626442], [44, 7.351983], [59, 14.587265], [68, 15.385357], [77, 16.365351], [84, 16.184529], [94, 18.344505], [108, 41.227187], [117, 39.37891], [128, 40.724853]], "label": "Google sparsehash 2.0 sparse_hash_map"}, {"data": [[7, 0.164012], [10, 0.196725], [22, 0.674874], [34, 1.378056], [44, 1.457056], [59, 1.766007], [68, 2.83264], [77, 2.559138], [84, 2.73269], [94, 2.969715], [108, 3.183305], [117, 3.099282], [128, 3.314104]], "label": "Google sparsehash 2.0 dense_hash_map"}, {"data": [[7, 0.62334], [10, 0.896382], [22, 2.836475], [34, 4.820623], [44, 5.454768], [59, 8.68892], [68, 9.822701], [77, 9.247], [84, 10.225132], [94, 12.206556], [108, 15.684576], [117, 15.788265], [128, 16.734827]], "label": "Boost 1.57 unordered_map"}, {"data": [[7, 0.438406], [10, 0.549438], [22, 0.69154], [34, 1.324668], [44, 1.767032], [59, 2.356399], [68, 3.339673], [77, 3.618639], [84, 3.978056], [94, 4.786716], [108, 5.719606], [117, 6.410732], [128, 7.284667]], "label": "Boost 1.57 container/flat_map"}], "query_random": [{"data": [[7, 1.437126], [10, 1.780534], [22, 2.134941], [34, 2.592437], [44, 3.032842], [59, 3.384666], [68, 3.2827], [77, 3.150921], [84, 3.359862], [94, 3.607361], [108, 4.09756], [117, 3.97718], [128, 3.939264]], "label": "GCC 4.8.2 std::map"}, {"data": [[7, 2.994385], [10, 3.449125], [22, 3.717252], [34, 3.119746], [44, 3.807377], [59, 3.093871], [68, 3.303348], [77, 3.401457], [84, 3.536373], [94, 3.763217], [108, 2.871974], [117, 2.917151], [128, 2.999574]], "label": "GCC 4.8.2 std::unordered_map"}, {"data": [[7, 1.408497], [10, 1.912621], [22, 3.993406], [34, 3.627917], [44, 5.541751], [59, 3.285898], [68, 3.889345], [77, 4.694517], [84, 4.95274], [94, 5.960179], [108, 3.090273], [117, 3.26882], [128, 3.579417]], "label": "Google sparsehash 2.0 sparse_hash_map"}, {"data": [[7, 0.712499], [10, 1.006673], [22, 1.014273], [34, 0.879282], [44, 1.097076], [59, 1.484884], [68, 0.884689], [77, 0.967289], [84, 0.941574], [94, 1.203366], [108, 1.402282], [117, 1.488052], [128, 1.504695]], "label": "Google sparsehash 2.0 dense_hash_map"}, {"data": [[7, 2.765428], [10, 3.28057], [22, 3.668774], [34, 3.626416], [44, 3.907296], [59, 3.550368], [68, 3.809431], [77, 3.702852], [84, 3.959559], [94, 4.435955], [108, 3.419833], [117, 3.369579], [128, 3.506896]], "label": "Boost 1.57 unordered_map"}, {"data": [[7, 1.643326], [10, 1.924941], [22, 2.233269], [34, 2.909318], [44, 3.297877], [59, 3.558162], [68, 3.54885], [77, 3.31426], [84, 3.584803], [94, 3.906225], [108, 4.057794], [117, 3.841046], [128, 4.066772]], "label": "Boost 1.57 container/flat_map"}]}
$(function () {
    $.plot($("#query_random"), chart_data['query_random'], runtime_settings);
    $.plot($("#query_ordered"), chart_data['query_ordered'], runtime_settings);
    $.plot($("#insert_random"), chart_data['insert_random'], runtime_settings);
    $.plot($("#insert_ordered"), chart_data['insert_ordered'], runtime_settings);
});
&lt;/script&gt;

&lt;style&gt;
div.chart {
    width: 700px;
    height: 230px;
}
div.xaxis-title {
    width: 700px;
    text-align: center;
    font-style: italic;
    font-size: small;
    color: #666;
}
&lt;/style&gt;

&lt;p&gt;Ordered insertion&lt;/p&gt;

&lt;div class="chart" id="insert_ordered"&gt;&lt;/div&gt;
&lt;div class="xaxis-title"&gt;number of keys&lt;/div&gt;

&lt;p&gt;Random insertion&lt;/p&gt;

&lt;div class="chart" id="insert_random"&gt;&lt;/div&gt;
&lt;div class="xaxis-title"&gt;number of keys&lt;/div&gt;

&lt;p&gt;Ordered queries&lt;/p&gt;

&lt;div class="chart" id="query_ordered"&gt;&lt;/div&gt;
&lt;div class="xaxis-title"&gt;number of keys&lt;/div&gt;

&lt;p&gt;Random queries&lt;/p&gt;

&lt;div class="chart" id="query_random"&gt;&lt;/div&gt;
&lt;div class="xaxis-title"&gt;number of keys&lt;/div&gt;

&lt;h3 id="summary"&gt;Summary&lt;/h3&gt;
&lt;p&gt;Generally speaking, the &lt;code&gt;google::dense_hash_map&lt;/code&gt; is still the best choice if you are aggressively purchasing the speed performance.
Experimental result confirms that the &lt;code&gt;dense_hash_map&lt;/code&gt; achieves both the fastest insertion and fastest querying.&lt;/p&gt;

&lt;p&gt;Also, we see that on the condition that the number of keys is relatively small, the sorted group (&lt;code&gt;std::map&lt;/code&gt; and &lt;code&gt;boost::container::flat_map&lt;/code&gt;) performs better than the hash group.
One thing we need to note that, after the number of key increase to about 100, the sorted group starts to perform poor compared to the hash group.&lt;/p&gt;

&lt;p&gt;By comparing the &lt;code&gt;std::map&lt;/code&gt; and &lt;code&gt;boost::container::flat_map&lt;/code&gt;, their performances are almost identical.
I am a little disappointed by this fact because I always considering the &lt;code&gt;boost::container::flat_map&lt;/code&gt; as a silver bullet for the few key mapping problems.&lt;/p&gt;

&lt;p&gt;For practice, there are several suggestion:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;For the mapping problem with less than 100 keys, &lt;code&gt;std::map&lt;/code&gt; is still a solution. It’s especially true if ordered keys is in your concern.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;google::dense_hash_map&lt;/code&gt; is still number one choice, if memory and the annoying &lt;code&gt;set_empty_key()&lt;/code&gt; are both not the problems.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Parallel and HPC with Python (or numpy)</title>
    <link rel="alternate" href="http://yjliu.net/blog/2014/04/25/parallel-in-python.html"/>
    <id>http://yjliu.net/blog/2014/04/25/parallel-in-python.html</id>
    <published>2014-04-24T16:00:00Z</published>
    <updated>2014-11-20T09:24:26+08:00</updated>
    <author>
      <name>Article Author</name>
    </author>
    <content type="html">&lt;p&gt;For guys working with natural language processing problems, it’s daily task to process
tons of data. To handle the millions of lines of sentences, I would prefer C/C++ or
Java in the past, especially at certain scenario like performing machine learning algorithm
onto the data. However, in this days, I wrote a very slow python program (and working around
&lt;code&gt;numpy&lt;/code&gt;, it’s an important clue for future story). After wasting too much time on this single
thread program, I decided to parallel it.&lt;/p&gt;

&lt;h3 id="buzz-in-the-task"&gt;Buzz in the task&lt;/h3&gt;

&lt;p&gt;Let me briefly introduce my task (It’s usually important for choosing the appropriate
parallel model). I have a collection of data which contains about 200 thousand entries.
My algorithm is some kind of &lt;code&gt;loop-loop&lt;/code&gt; and can be illustrated as the following pseudocode.&lt;/p&gt;

&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;terminal&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_vector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;consuming&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;do&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_vector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since the &lt;code&gt;time-consuming-process&lt;/code&gt; is very time consuming, we can easily use a &lt;code&gt;producer&lt;/code&gt;
to distribute these tasks onto several &lt;code&gt;consumers&lt;/code&gt;. What a textbook parallel model! To
make it more clear, also for convenience of future discussion, let me put it into some
meaningless but runnable code.&lt;/p&gt;

&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="kn"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;nr_instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;
&lt;span class="n"&gt;nr_dim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;257241&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;                 &lt;span class="c"&gt;# use to simulate the time consuming&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c"&gt;# numpy array operation.&lt;/span&gt;
    &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_instances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_vector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="s"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;"iter &lt;/span&gt;&lt;span class="si"&gt;%&lt;/span&gt;&lt;span class="s"&gt;d is done."&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A simple &lt;code&gt;time&lt;/code&gt; command shows the above code runs &lt;code&gt;1m29.155s&lt;/code&gt; on my server.&lt;/p&gt;

&lt;h3 id="threading"&gt;Threading&lt;/h3&gt;

&lt;p&gt;As I mentioned before, I decide to paralled the above code. First thing that came into
my mind is the &lt;strong&gt;threading&lt;/strong&gt;. According to my past experience, multi-threaded programming
is always the best choice when you have a server with several cores.&lt;/p&gt;

&lt;p&gt;Distributing the producer’s to several thread can be painless done with python &lt;code&gt;threading&lt;/code&gt;
module. The producer’s job is dividing the instances into several groups, feed them to each
of the thread and wait all these threads finish their work. A wrapper for the consumer is
implemented for recieveing data and invoke meta-consumer process.&lt;/p&gt;

&lt;p&gt;After a slight modification on the above program, it became the multi-threaded version.&lt;/p&gt;

&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="kn"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;threading&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;basic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nr_instances&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nr_dim&lt;/span&gt;

&lt;span class="n"&gt;nr_threads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;consumer_wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;global_vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global_vector&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_instances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;nr_threads&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;nr_threads&lt;/span&gt;
    &lt;span class="n"&gt;fence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nr_instances&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;nr_threads&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_threads&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;nr_instances&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fence&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;fence&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;consumer_wrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_threads&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_vector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="s"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;"iter &lt;/span&gt;&lt;span class="si"&gt;%&lt;/span&gt;&lt;span class="s"&gt;d is done."&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I was expecting that the multi-threaded version will bring 2 to 3 times speed up if I
config the program with 4 threads. However, this code run &lt;code&gt;1m33.678s&lt;/code&gt; on the same server.
I can’t even believe that a multi-threaded program runs slower than the single-threaded
program.&lt;/p&gt;

&lt;p&gt;After a survey on this issue, I found the answer. It suffer from the Python GIL which
prevent the script running on two cores. There are lots of article talking about the
GIL problems, so I won’t write more on this. The conclusion is that &lt;em&gt;multi-threaded in
Python doesn’t work for my task&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id="multiprocessing"&gt;Multiprocessing&lt;/h3&gt;

&lt;p&gt;The failure of multi-threaded program drive me to seek for some alternative and I found
the &lt;code&gt;multiprocessing&lt;/code&gt; module. At the begining of its document page, it says,&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To my understanding, the mechanism of multiprocessing module is treating the each thread
as a process. When creating a thread, it actually copy(fork) the entire processing into
a new process.&lt;/p&gt;

&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="kn"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;multiprocessing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Pool&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;basic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nr_instances&lt;/span&gt;

&lt;span class="n"&gt;nr_threads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;consumer_wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;global_vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;global_vector&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_instances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nr_threads&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;L&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nr_instances&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;nr_threads&lt;/span&gt;
    &lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fence&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;nr_threads&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fence&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt; \
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_threads&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;consumer_wrapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_vector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="s"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;"iter &lt;/span&gt;&lt;span class="si"&gt;%&lt;/span&gt;&lt;span class="s"&gt;d fin"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It takes &lt;code&gt;0m33.970s&lt;/code&gt; for the multiprocessing version to run. The multiprocessing module
bring in about 2.5 times speed up.&lt;/p&gt;

&lt;p&gt;However, one disappointing feature of multiprocessing is it copy entire program, therefore
resulting in large memory consumption. This feature make it very unscalable if the &lt;em&gt;single
process version&lt;/em&gt; consume a lot of memory. In my experiments, my script consume 8G memory.
If I apply it to 8 processors, the program explode into 64G (or more), almost reach the
limit of the server.&lt;/p&gt;

&lt;h3 id="mpi"&gt;MPI&lt;/h3&gt;

&lt;p&gt;The first time I meet &lt;code&gt;MPI&lt;/code&gt; is that I read some source code of a machine-translation toolkit.
The MPI module is embeded in a mess of C++ code and make it very difficult to understand.&lt;/p&gt;

&lt;p&gt;Now it came to me again because the document page claims that&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;MPI is not an IEEE or ISO standard, but has in fact, become the “industry standard”
for writing message passing programs on HPC platforms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My supervisor also endorse it. It seems a widely used library for parallel programming.
And its Python embedding also makes it less painful (or painless) to use.&lt;/p&gt;

&lt;p&gt;In MPI, the producer-consumer model can be very clearly implemented by letting the zero-ranked
(or master) program distribute the instances (or tasks), keep recieveing data from consumer.
Running status of the consumers can be easily obtain by check the &lt;code&gt;tag&lt;/code&gt; field of the recieved
data.&lt;/p&gt;

&lt;p&gt;Revisiting my problem, the MPI version is shown blow.&lt;/p&gt;

&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="kn"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mpi4py&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MPI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;basic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nr_instances&lt;/span&gt;

&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EXIT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;comm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MPI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COMM_WORLD&lt;/span&gt;
&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;
&lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rank&lt;/span&gt;
&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MPI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;consumer_daemon&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MPI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get_processor_name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;READY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MPI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ANY_TAG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get_tag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;
            &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DONE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EXIT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;EXIT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_instances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;L&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fence&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fence&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;START&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;finished&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nr_dim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;finished&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MPI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ANY_SOURCE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MPI&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ANY_TAG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get_tag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;DONE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;global_vector&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
            &lt;span class="n"&gt;finished&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_vector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="s"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;"iter &lt;/span&gt;&lt;span class="si"&gt;%&lt;/span&gt;&lt;span class="s"&gt;d is done."&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;comm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;EXIT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;consumer_daemon&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Under same settings, the above program runs &lt;code&gt;0m31.332s&lt;/code&gt; and it memory performance is better
than the multiprocessing version. One reason for the faster speed, I think, is the consumer
wasn’t shut down between each iterations.&lt;/p&gt;

&lt;h3 id="summary"&gt;Summary&lt;/h3&gt;

&lt;p&gt;When it comes to the topic of paralleling in Python, my advice is avoid using &lt;code&gt;threading&lt;/code&gt;
especially with some code that will trigger GIL. If the task only takes a little memory,
my advice is the &lt;code&gt;multiprocessing&lt;/code&gt;, because it’s easier to use and easier to switch from
threading-oriented program. If you decide to make it a &lt;em&gt;real&lt;/em&gt; paralleled program (aka, 
using it on multi-cores server or even across several servers), mpi4py is no doubt a better
choice.&lt;/p&gt;

&lt;h4 id="reference"&gt;Reference&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;There are also some unlucky guys who found Python threading is slower: &lt;a href="http://stackoverflow.com/questions/3121109/python-threading-unexpectedly-slower"&gt;Python threading unexpectedly slower&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Introduction to MPI : &lt;a href="https://computing.llnl.gov/tutorials/mpi/"&gt;Message Passing Interface (MPI)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;And the Python embedding : &lt;a href="http://mpi4py.scipy.org/"&gt;MPI4Py - SciPy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;And some fancy examples! : &lt;a href="https://github.com/jbornschein/mpi4py-examples"&gt;jbornschein/mpi4py-examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>研一这一年吧</title>
    <link rel="alternate" href="http://yjliu.net/blog/2013/08/05/summary-on-first-year-as-graduate-student.html"/>
    <id>http://yjliu.net/blog/2013/08/05/summary-on-first-year-as-graduate-student.html</id>
    <published>2013-08-04T17:07:11Z</published>
    <updated>2014-11-20T09:24:26+08:00</updated>
    <author>
      <name>Article Author</name>
    </author>
    <content type="html">&lt;p&gt;给这一年列一个时间表吧，这篇文章想写很久了，虽然有预感写出来又是满满的负能量。&lt;/p&gt;

&lt;h3 id="section"&gt;2012年&lt;/h3&gt;

&lt;h4 id="section-1"&gt;8月-9月&lt;/h4&gt;
&lt;p&gt;写了一篇叫《基于序列标注的中文分词、词性标注模型比较分析》，投了一个学生会议。大概是想论证用分类方法做分词、词性标注这些序列性问题可以取得与序列标注模型类似的性能。还想强调分类速度比较快。不过实验并没有获得符合预期的结果。所以这篇论文的论点比较奇怪，不管是写还是修改都很痛苦。在后来被转投中文信息学报，我又不得不痛苦地改了一遍。&lt;/p&gt;

&lt;h4 id="section-2"&gt;9月-10月&lt;/h4&gt;
&lt;p&gt;参加了微博分词的评测。最后提交的系统是一个混了一大坨预处理的特征、半监督特征的CRF模型。除了把别人论证过的东西实现了一通后，几乎没有引入什么有新意的东西。由于官方没公布评测排名，并不知道自己的系统排名如何，但开会时统计了一下，大概是第二的位置。大概半年后，我review这个系统时发现当时使用crfsuite工具训练模型时没把负特征开关打开，所以最终结果应该是高于提交的系统的结果的。但主办方也没公布数据，也没法去做实验。&lt;/p&gt;

&lt;h4 id="section-3"&gt;10月-11月&lt;/h4&gt;
&lt;p&gt;拿出不多的时间学习了机器学习，包括实现了一些简单的机器学习算法。重组织了博客。调研了一部分domain adaptation的论文，改之前的水文。还有一些杂七杂八的上课实验什么的。&lt;/p&gt;

&lt;h4 id="section-4"&gt;11月-12月&lt;/h4&gt;
&lt;p&gt;写微博分词的评测报告，同时也看一段gibbs抽样。准备去上海开会的报告以及去开会，接着改论文投中文信息学报。&lt;/p&gt;

&lt;h4 id="section-5"&gt;12月-1月&lt;/h4&gt;
&lt;p&gt;前半段考试，做了一坨课程实验，后半段去天津开了微博分词的会，其间都是准备poster一些杂事。这月后半段开始接了网管的工作。这其间还草草做了一个字聚类帮助分词的实验。后来这个非常烂的idea投了ccl2013。&lt;/p&gt;

&lt;h3 id="section-6"&gt;2013年&lt;/h3&gt;

&lt;h4 id="section-7"&gt;1月-2月&lt;/h4&gt;
&lt;p&gt;前半段修硬盘来着。刚接手网管，实验室的磁盘阵列就挂了。大概原因就是raid5坏了两块后没人知道，第三块坏后就彻底挂了。大冬天抱着硬盘跑数据恢复，反正是非常苦逼。后来十天草草准备了一下托福，一战成了挂逼。&lt;/p&gt;

&lt;h4 id="section-8"&gt;2月-3月&lt;/h4&gt;
&lt;p&gt;打算考G，利用过年时间背了一个多月单词，约了5月的G和6月的T。&lt;/p&gt;

&lt;h4 id="section-9"&gt;3月-5月&lt;/h4&gt;
&lt;p&gt;开始调研用deep learning做分词，基本把rnnlm看了一遍。最初的思路是用语言模型做分词，结果做出来就让人没什么信心，后来又把思路换成用embedding做semi-supervised，也没什么信心。当时觉得主要问题在embedding结果对于分词模型不是线性作用的。也想过用c&amp;amp;w直接做一个分词的神经网络，不过后来看ccl好像有中科院的同学用实现了这个思路，不过效果似乎也让人没什么信心。不知道dl是不是不适合参加自然语言处理的battle against state-of-the-art。&lt;/p&gt;

&lt;p&gt;断断续续地准备英语。&lt;/p&gt;

&lt;p&gt;这两个月中做的另外一件事是机房上新设备。配上机器，电路改造，修空调，反正很少能安心下来看看书或者读读论文，跑实验也总出错。&lt;/p&gt;

&lt;h4 id="section-10"&gt;5月-6月&lt;/h4&gt;
&lt;p&gt;面对一坨考试，终于撑不住了。取消的5月的G。不过考试还是成功考出两科60分。&lt;/p&gt;

&lt;h4 id="section-11"&gt;6月-8月&lt;/h4&gt;
&lt;p&gt;在万念俱灰的情绪下，用一个星期整理了之前cluster帮助分词的工作。想论证怎样做字的表示才能帮助分词任务，结论是对单个字做不靠谱，对字聚类时要考虑字的上下文信息。这个水文投出去后重构了正华师兄的依存句法分析器dparser。当时估计工作量大概是一个月，1万行代码以下。但是实际做起来发现可以顺势将ltp里面的其他模块也重构一下。结果就是重写了本科毕设的序列标注统一框架，整个项目下来有1.7万行代码。还有9K字的文档，再加上写了python和ruby两个版本的client和一部分web页面。总之这两个月彻底做了一只代码狗。&lt;/p&gt;

&lt;p&gt;6月末托福二战，再次准备十天，再次挂逼，考了个什么都不能做的93。基本是死了出国这条心了。
再一件事是实验室网站被挂马，被网络中心关站了。没办法用静态页生成器重构了主页，迁移+升级了服务器，跑了几趟网络中心。现在还有一些服务没恢复，拙计。&lt;/p&gt;

&lt;p&gt;这一年，基本上是在一种忙碌而压抑的状态中度过。没怎么过过周末，也没时间去运动。体重又回到了110斤以下，可悲的是肚子好像有胖的趋势。前个周末，爸妈来哈尔滨，幸亏没买到车票。因为那天综合楼停电，结果来电后机房就烧到50度了。若是他们来，恐怕只能把他们撂旅馆里一天了。&lt;/p&gt;

&lt;p&gt;有的时候，我也不知道想过什么应该怎样生活。也没时间去想一想，反正一直被无形的力量推动，不由自主。&lt;/p&gt;

&lt;p&gt;他们大四的毕业那会儿，我有几次被三点唱歌的醉汉们吵醒。只好去公寓平台的椅子里乘凉，有时看天色由黑转灰，继而一片青蓝，觉得很陌生。&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>脱臼</title>
    <link rel="alternate" href="http://yjliu.net/blog/2013/07/21/luxation.html"/>
    <id>http://yjliu.net/blog/2013/07/21/luxation.html</id>
    <published>2013-07-21T04:28:17Z</published>
    <updated>2014-11-20T09:24:26+08:00</updated>
    <author>
      <name>Article Author</name>
    </author>
    <content type="html">&lt;p&gt;昨天睡觉前，躺在床上打了个哈欠，结果一不小心下巴脱臼了。&lt;/p&gt;

&lt;p&gt;下巴脱臼已经不是一次两次了。第一次脱臼好像是由于吃苹果张太大口，后来则以打哈欠打脱臼了居多。我把这种病症归咎于基因，因为印象中我妈好像也脱臼过。可能是骨骼的构造不合适，也可能是韧带的力度不够，不过这些一定是由基因决定的。由于接受了这种设定，我也就比较释然，重来没埋怨过苹果或者是哈欠。&lt;/p&gt;

&lt;p&gt;出于多次脱臼的经验，我已经学会了一些基本的救治手段。一般是将下巴向左稍用力顶一下，感觉头骨错动，也可能会听到咯噔一声。如果运气好，脱臼就归位了。运气不好就多试几次，总有那么一次成功的。&lt;/p&gt;

&lt;p&gt;我对自己的身体还有自己的技术都是有一定信心的，所以躺在床上左手扶头，右手扶下巴，向左用了一下力。可惜没出现咯噔一声。我知道我失败了，休息了几秒，换了个姿势，又向左使了一下力，当然还是失败。“或许是躺着不方便”，这么想后，我便坐了起来，哈尔滨夏夜的凉风慢悠悠地从窗子吹了进来。我额头上有汗，所以敏锐地捕捉到了这阵不期而遇的夏天的风。&lt;/p&gt;

&lt;p&gt;坐起来后，我又重复了几次相同的自救策略，都以失败告终。好在我并没有着急，大学这几年唯一教会我的就是在着急之前先平静一下。平静的片刻之后，一大坨信息就冲入我的脑中：“首都机场好像发生爆炸案了”；“是不是城管最近又打死人了”；“托福口语如何提高成绩，真着急”；“昨天复华那边打架来着”；“不知道当年温岚有没有和周杰伦好过”；“女神建议我换个孙燕姿的桌面，要不要考虑一下”；“最近好像写了很多代码，都快成狗了”；“哎，活着真没意思”；“不过我还是不要告诉别人，免得看起来像个怨妇”。&lt;/p&gt;

&lt;p&gt;在一阵激烈的对于宇宙终极问题的思考之后，我意识到“这次脱臼好像是自己弄不好了。”&lt;/p&gt;

&lt;p&gt;而这时，寝室里另外一个哥们打起了呼噜，配着青黑天空中闪烁的繁星，显得非常有节奏。&lt;/p&gt;

&lt;p&gt;大概又经历了一次尝试的失败，我放弃了治疗。小心翼翼穿上衣服。我要去医院，这件事不怎么严重，不必惊动其他人，我自己就够了。&lt;/p&gt;

&lt;p&gt;“我是多么独立的一个人”， 我这么想着瞄了一眼寝室的镜子，以确保自己脱臼的嘴脸在旁人看起来不那么可憎。&lt;/p&gt;

&lt;p&gt;然后，一切妥当后，我拖着着这副夸张的对世界惊呆了的表情走入了孤独的夜色之中。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.oneplus.info/wp-content/uploads/2013/07/暴走漫画-www.iPc_.me33.png"&gt;&lt;img src="http://blog.oneplus.info/wp-content/uploads/2013/07/暴走漫画-www.iPc_.me33.png" alt="" title="superize" width="118" height="145" class="aligncenter size-full wp-image-820" /&gt;&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
</feed>