<?xml version="1.0" encoding="utf-8" ?>


<?xml-stylesheet href="http://d.hatena.ne.jp/Glass_saga/rssxsl" type="text/xsl" media="screen"?>


<rdf:RDF
xmlns="http://purl.org/rss/1.0/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xml:lang="ja">
<channel rdf:about="http://d.hatena.ne.jp/Glass_saga/rss">
<title>Glass_saga</title>
<link>http://d.hatena.ne.jp/Glass_saga/</link>
<description>Glass_saga</description>

<dc:creator>Glass_saga</dc:creator>
<dc:date>2012-03-24T10:03:50+09:00</dc:date>
<items>
<rdf:Seq>
<rdf:li rdf:resource="http://d.hatena.ne.jp/Glass_saga/20120222/1329901140"/>
<rdf:li rdf:resource="http://d.hatena.ne.jp/Glass_saga/20110815/1313393315"/>
<rdf:li rdf:resource="http://d.hatena.ne.jp/Glass_saga/20110627/1309188591"/>
<rdf:li rdf:resource="http://d.hatena.ne.jp/Glass_saga/20110602/1307001725"/>
<rdf:li rdf:resource="http://d.hatena.ne.jp/Glass_saga/20110601/1306900529"/>
</rdf:Seq>
</items>
</channel>



<item rdf:about="http://d.hatena.ne.jp/Glass_saga/20120222/1329901140">
<title>[ruby] IO.copy_streamで出力先がsocketでない場合でもsendfile()を使う</title>
<link>http://d.hatena.ne.jp/Glass_saga/20120222/1329901140</link>
<description> ※結論から言うと速くならなかった。 rubyのIO.copy_streamは可能であればsendfile()を用いるが、これは出力先がsocketである場合に限定されていた。 Linux 2.6.33以降ではsendfile()の出力先が通常のファイルでも許されるようになっていた( sendfile(2) - Linux man page )</description>

<content:encoded><![CDATA[
<div class="section">
<p>※結論から言うと速くならなかった。</p>
<p>rubyのIO.copy_streamは可能であればsendfile()を用いるが、これは出力先がsocketである場合に限定されていた。</p>
<p>Linux 2.6.33以降ではsendfile()の出力先が通常のファイルでも許されるようになっていた( <a href="http://linux.die.net/man/2/sendfile" target="_blank">sendfile(2) - Linux man page</a> )ので、試してみた。</p>
<p>(実行した環境は、Ubuntu 11.10 3.0.0-15-server)</p>
<pre class="syntax-highlight">
<span class="synType">diff --git a/io.c b/io.c</span>
index f404b53..181897f 100644
<span class="synType">--- a/io.c</span>
<span class="synType">+++ b/io.c</span>
<span class="synStatement">@@ -9424,8 +9424,6 @@</span><span class="synPreProc"> nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)</span>
         stp-&#62;error_no = errno;
         return -1;
     }
<span class="synSpecial">-    if ((dst_stat.st_mode &#38; S_IFMT) != S_IFSOCK)</span>
<span class="synSpecial">-        return 0;</span>
 
     src_offset = stp-&#62;src_offset;
     use_pread = src_offset != (off_t)-1;
</pre>

<p>このpatchをtrunkに適用すると通常のファイル同士のコピーでもsendfile()を使うようになる。</p>
<p>(実際にsendfile()を使っているかどうか確認するにはstraceが便利)</p>
<pre>
dd if=/dev/zero of=dummy bs=1M count=100
</pre>

<p>として作成したファイルを使って</p>
<pre class="syntax-highlight">
<span class="synPreProc">require</span> <span class="synSpecial">'</span><span class="synConstant">benchmark</span><span class="synSpecial">'</span>

<span class="synIdentifier">Benchmark</span>.bm <span class="synStatement">do</span> |<span class="synIdentifier">x</span>|
  x.report <span class="synStatement">do</span>
    <span class="synIdentifier">IO</span>.copy_stream(<span class="synSpecial">&#34;</span><span class="synConstant">dummy</span><span class="synSpecial">&#34;</span>, <span class="synSpecial">&#34;</span><span class="synConstant">dst</span><span class="synSpecial">&#34;</span>)
  <span class="synStatement">end</span>
<span class="synStatement">end</span>
</pre>

<p>このようなベンチマークを実行した。</p>
<p>それぞれ実行前に</p>
<pre>
sudo sysctl -w vm.drop_caches=1
</pre>

<p>した上での結果である。</p>
<h4> trunk(r34734) # read() and write()</h4>
<pre>
       user     system      total        real
   0.000000   0.360000   0.360000 (  0.702267)

       user     system      total        real
   0.000000   0.370000   0.370000 (  0.755613)

       user     system      total        real
   0.000000   0.390000   0.390000 (  0.724757)
</pre>

<h4> proposal # sendfile()</h4>
<pre>
       user     system      total        real
   0.000000   0.330000   0.330000 (  0.713097)

       user     system      total        real
   0.000000   0.400000   0.400000 (  0.737590)

       user     system      total        real
   0.000000   0.350000   0.350000 (  0.717704)
</pre>

<p>速くならなかった。</p>
<p>man pageには</p>
<blockquote>
<p>Because this copying is done within the kernel, sendfile() is more efficient than the combination of read(2) and write(2), which would require transferring data to and from user space.</p>
</blockquote>
<p>とあるけれど、通常のファイル同士のコピーではそれほど恩恵が得られないようだ。</p>
</div>
]]></content:encoded>
<dc:creator>Glass_saga</dc:creator>
<dc:date>2012-02-22T17:59:00+09:00</dc:date>
<dc:subject>ruby</dc:subject>
</item>
<item rdf:about="http://d.hatena.ne.jp/Glass_saga/20110815/1313393315">
<title>[spcamp][Ruby] セキュリティ&amp;プログラミングキャンプ2011に参加した</title>
<link>http://d.hatena.ne.jp/Glass_saga/20110815/1313393315</link>
<description> プログラミング言語クラスに参加した。 講義の内容についてはどこかで見られると思うので、個別課題について書く。 個別課題の内容 rubyのpreludeのprecompileという課題に取り組んだ。 preludeというのはインタプリタの起動時に実行されるRubyスクリプトで、内容は MUTEX_F</description>

<content:encoded><![CDATA[
<div class="section">
<p>プログラミング言語クラスに参加した。</p>
<p>講義の内容についてはどこかで見られると思うので、個別課題について書く。</p>
<h4> 個別課題の内容</h4>
<p>rubyのpreludeのprecompileという課題に取り組んだ。</p>
<p>preludeというのはインタプリタの起動時に実行されるRubyスクリプトで、内容は</p>

<ul>
<li> MUTEX_FOR_THREAD_EXCLUSIVE(排他制御などに利用する為のVMグローバルなMutex)の定義</li>
<li> rubygem.rbのrequire</li>
<li> enc/encdb.so(エンコーディングの定義とそのエイリアス) enc/trans/transdb.so(各エンコーディング間のトランスコーダ)のrequire</li>
</ul>
<p>である。</p>
<p>preludeのRubyコードはprelude.cにCの文字列として埋めこまれていて、rubyは起動時に毎回このコードをYARVの命令列にコンパイルして実行している。</p>
<p>preludeの内容は一旦ビルドしてしまえば変わらないので、前もって命令列にコンパイルしておいて(precompile)、インタプリタの起動時にはこれを直接実行すれば高速化が期待できるのではないかと考えた。</p>
<h4> 結果</h4>
<p>prelude.cはrubyのビルドプロセス内でtool/compile_prelude.rbから生成されているので、ここを弄った。</p>
<p>まずはpreludeの内容をcompileしてファイルに書き出しておき、rubyの起動時にそれを読んで実行するという手っ取り早い方法を試したが、これではprecompile無しと比較して6%ほど遅い。</p>
<p>そこで命令列をprelude.cに埋め込んでみたが、これでも3%ほど遅くなってしまった。</p>
<h4> 考察</h4>
<p>prelude.cに命令列を埋め込んでもまだ遅いという事は、コードをcompileするよりも文字列から命令列を得る方がかえって時間がかかるという事を示している。</p>
<p>つまりMarshal.loadでは遅い。</p>
<p>precompileで高速化を狙うには、命令列を高速にloadできるような形式を考える必要がある。</p>
<h4> 発表</h4>
<p>やっている事はシンプルなのに、発表後に「難しい事をされていたんですね」と参加者から言われてしまった。</p>
<p>発表時間が2分しか与えられなかった事を差し引いても、限られた時間で要点を伝える能力の不足を感じた。</p>
<h4> スライド</h4>
<p><a href="http://www.slideshare.net/Glass_saga/preludeprecompile" target="_blank">http://www.slideshare.net/Glass_saga/preludeprecompile</a></p>
</div>
]]></content:encoded>
<dc:creator>Glass_saga</dc:creator>
<dc:date>2011-08-15T16:28:35+09:00</dc:date>
<dc:subject>spcamp</dc:subject>
<dc:subject>Ruby</dc:subject>
</item>
<item rdf:about="http://d.hatena.ne.jp/Glass_saga/20110627/1309188591">
<title>[Ruby] Queueのどうでも良い話</title>
<link>http://d.hatena.ne.jp/Glass_saga/20110627/1309188591</link>
<description> thread.rbでQueue#.popがこのように定義されている。 def pop(non_block=false) @mutex.synchronize{ while true if @que.empty? raise ThreadError, &#34;queue empty&#34; if non_block @waiting.push Thread.current @mutex.sleep else return @que.shift end end } end </description>

<content:encoded><![CDATA[
<div class="section">
<p>thread.rbでQueue#.popがこのように定義されている。</p>
<pre class="syntax-highlight">
 <span class="synPreProc">def </span><span class="synIdentifier">pop</span>(non_block=<span class="synConstant">false</span>)
    <span class="synIdentifier">@mutex</span>.synchronize{
      <span class="synStatement">while</span> <span class="synConstant">true</span>
        <span class="synStatement">if</span> <span class="synIdentifier">@que</span>.empty?
          <span class="synStatement">raise</span> <span class="synIdentifier">ThreadError</span>, <span class="synSpecial">&#34;</span><span class="synConstant">queue empty</span><span class="synSpecial">&#34;</span> <span class="synStatement">if</span> non_block
          <span class="synIdentifier">@waiting</span>.push <span class="synIdentifier">Thread</span>.current
          <span class="synIdentifier">@mutex</span>.sleep
        <span class="synStatement">else</span>
          <span class="synStatement">return</span> <span class="synIdentifier">@que</span>.shift
        <span class="synStatement">end</span>
      <span class="synStatement">end</span>
    }
  <span class="synPreProc">end</span>
</pre>

<p>そこで、次のようなコードを実行すると</p>
<pre class="syntax-highlight">
<span class="synPreProc">require</span> <span class="synSpecial">'</span><span class="synConstant">thread</span><span class="synSpecial">'</span>

queue = <span class="synIdentifier">Queue</span>.new

t = <span class="synIdentifier">Thread</span>.start <span class="synStatement">do</span>
  <span class="synStatement">loop</span>{ queue.pop }
<span class="synStatement">end</span>

<span class="synConstant">2</span>.times <span class="synStatement">do</span>
  <span class="synConstant">nil</span> <span class="synStatement">until</span> t.stop?
  t.wakeup
<span class="synStatement">end</span>

<span class="synConstant">nil</span> <span class="synStatement">until</span> t.stop?

queue.instance_eval{ p <span class="synIdentifier">@waiting</span> }
p queue.num_waiting
</pre>

<p>以下のようになる。</p>
<pre>
&#91;#&#60;Thread:0x00000001899698 sleep&#62;, #&#60;Thread:0x00000001899698 sleep&#62;, #&#60;Thread:0x00000001899698 sleep&#62;]
3
</pre>

<p>本当にどうでも良い。</p>
</div>
]]></content:encoded>
<dc:creator>Glass_saga</dc:creator>
<dc:date>2011-06-28T00:29:51+09:00</dc:date>
<dc:subject>Ruby</dc:subject>
</item>
<item rdf:about="http://d.hatena.ne.jp/Glass_saga/20110602/1307001725">
<title>[OpenCV] cvAvgを用いた標本分散フィルタ</title>
<link>http://d.hatena.ne.jp/Glass_saga/20110602/1307001725</link>
<description> 指定したサイズのROIをずらしながら、ROI内の画素の標本分散を出力するフィルタを書いた。 #include &#60;math.h&#62; #include &#34;cv.h&#34; #include &#34;highgui.h&#34; void VarianceFilter(IplImage *src, IplImage* dst, int w_size); int main(int argc, char *ar</description>

<content:encoded><![CDATA[
<div class="section">
<p>指定したサイズのROIをずらしながら、ROI内の画素の標本分散を出力するフィルタを書いた。</p>
<pre class="syntax-highlight">
<span class="synPreProc">#include </span><span class="synConstant">&#60;math.h&#62;</span>
<span class="synPreProc">#include </span><span class="synConstant">&#34;cv.h&#34;</span>
<span class="synPreProc">#include </span><span class="synConstant">&#34;highgui.h&#34;</span>

<span class="synType">void</span> VarianceFilter(IplImage *src, IplImage* dst, <span class="synType">int</span> w_size);

<span class="synType">int</span> main(<span class="synType">int</span> argc, <span class="synType">char</span> *argv[]){
  IplImage *img, *dst;

  img = cvLoadImage(argv[<span class="synConstant">1</span>], CV_LOAD_IMAGE_GRAYSCALE); <span class="synComment">/* 画像をグレースケールで読み込む */</span>
  dst = cvCreateImage(cvSize(img-&#62;width, img-&#62;height), IPL_DEPTH_8U, <span class="synConstant">1</span>);

  VarianceFilter(img, dst, <span class="synConstant">3</span>); <span class="synComment">/* 標本分散フィルタ */</span>

  cvSaveImage(<span class="synConstant">&#34;result.jpg&#34;</span>, dst, <span class="synConstant">0</span>); <span class="synComment">/* 結果画像の保存 */</span>

  <span class="synComment">/* メモリの解放 */</span>
  cvReleaseImage(&#38;img);
  cvReleaseImage(&#38;dst);

  <span class="synStatement">return</span> <span class="synConstant">0</span>;
}

<span class="synComment">/*</span>
<span class="synComment">  標本平均フィルタ</span>
<span class="synComment">  引数:</span>
<span class="synComment">    src: 入力画像</span>
<span class="synComment">    dst: 出力先</span>
<span class="synComment">    w_size: ウィンドウサイズ</span>
<span class="synComment"> */</span>
<span class="synType">void</span> VarianceFilter(IplImage *src, IplImage* dst, <span class="synType">int</span> w_size){
  <span class="synType">int</span> i, j, wi, wj;
  <span class="synType">double</span> avg, e;
  uchar f;

  <span class="synStatement">for</span>(i=<span class="synConstant">0</span>; i&#60;src-&#62;height; i++){
    <span class="synStatement">for</span>(j=<span class="synConstant">0</span>; j&#60;src-&#62;width; j++){
      cvSetImageROI(src, cvRect(j, i, w_size, w_size)); <span class="synComment">/* ROIをセット */</span>
      avg = cvAvg(src, <span class="synConstant">NULL</span>).val[<span class="synConstant">0</span>]; <span class="synComment">/* ROI内の画素の標本平均 */</span>

      <span class="synComment">/* 標本分散の計算 */</span>
      e = <span class="synConstant">0.0</span>;
      <span class="synStatement">for</span>(wi=i; wi&#60;i+w_size; wi++){
        <span class="synStatement">for</span>(wj=j; wj&#60;j+w_size; wj++){
          f = CV_IMAGE_ELEM(src, uchar, wi, wj);
          e += pow(avg-f, <span class="synConstant">2</span>);
        }
      }
      e /= w_size * w_size;

      dst-&#62;imageData[dst-&#62;widthStep * i + j] = e; <span class="synComment">/* 出力 */</span>
    }
  }

  cvResetImageROI(src); <span class="synComment">/* ROIの解除 */</span>

  <span class="synStatement">return</span>;
}
</pre>

<p>入力画像</p>
<p><a href="http://f.hatena.ne.jp/Glass_saga/20110602165023" class="hatena-fotolife" target="_blank"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/G/Glass_saga/20110602/20110602165023.jpg" alt="f:id:Glass_saga:20110602165023j:image" title="f:id:Glass_saga:20110602165023j:image" class="hatena-fotolife"></a></p>
<p>結果</p>
<p><a href="http://f.hatena.ne.jp/Glass_saga/20110602170018" class="hatena-fotolife" target="_blank"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/G/Glass_saga/20110602/20110602170018.jpg" alt="f:id:Glass_saga:20110602170018j:image" title="f:id:Glass_saga:20110602170018j:image" class="hatena-fotolife"></a></p>
</div>
]]></content:encoded>
<dc:creator>Glass_saga</dc:creator>
<dc:date>2011-06-02T17:02:05+09:00</dc:date>
<dc:subject>OpenCV</dc:subject>
</item>
<item rdf:about="http://d.hatena.ne.jp/Glass_saga/20110601/1306900529">
<title>[OpenCV] cvCalcHistを用いたエントロピーフィルタ</title>
<link>http://d.hatena.ne.jp/Glass_saga/20110601/1306900529</link>
<description> 最近OpenCVを始めて、ふとエントロピーフィルタを書いてみようと思い立った。 ここではROIをずらしながらcvCalcHistでヒストグラムを求めるエントロピーフィルタについて書く。 #include &#60;math.h&#62; #include &#34;cv.h&#34; #include &#34;highgui.h&#34; void Entro</description>

<content:encoded><![CDATA[
<div class="section">
<p>最近OpenCVを始めて、ふとエントロピーフィルタを書いてみようと思い立った。</p>
<p>ここではROIをずらしながらcvCalcHistでヒストグラムを求めるエントロピーフィルタについて書く。</p>
<pre class="syntax-highlight">
<span class="synPreProc">#include </span><span class="synConstant">&#60;math.h&#62;</span>
<span class="synPreProc">#include </span><span class="synConstant">&#34;cv.h&#34;</span>
<span class="synPreProc">#include </span><span class="synConstant">&#34;highgui.h&#34;</span>

<span class="synType">void</span> EntropyFilter(IplImage *src, IplImage* dst, <span class="synType">int</span> w_size);

<span class="synType">int</span> main(<span class="synType">int</span> argc, <span class="synType">char</span> *argv[]){
  IplImage *img, *dst;

  img = cvLoadImage(argv[<span class="synConstant">1</span>], CV_LOAD_IMAGE_GRAYSCALE); <span class="synComment">/* 画像をグレースケールで読み込む */</span>
  dst = cvCreateImage(cvSize(img-&#62;width, img-&#62;height), IPL_DEPTH_8U, <span class="synConstant">1</span>);

  EntropyFilter(img, dst, <span class="synConstant">3</span>); <span class="synComment">/* エントロピーフィルタ */</span>

  cvSaveImage(<span class="synConstant">&#34;result.jpg&#34;</span>, dst, <span class="synConstant">0</span>); <span class="synComment">/* 結果画像の保存 */</span>

  <span class="synComment">/* メモリの解放 */</span>
  cvReleaseImage(&#38;img);
  cvReleaseImage(&#38;dst);

  <span class="synStatement">return</span> <span class="synConstant">0</span>;
}

<span class="synComment">/*</span>
<span class="synComment">  エントロピーフィルタ</span>
<span class="synComment">  引数:</span>
<span class="synComment">    src: 入力画像</span>
<span class="synComment">    dst: 出力先</span>
<span class="synComment">    w_size: ウィンドウサイズ</span>
<span class="synComment">*/</span>
<span class="synType">void</span> EntropyFilter(IplImage *src, IplImage* dst, <span class="synType">int</span> w_size){
  <span class="synType">int</span> i, j, k, hist_size = <span class="synConstant">256</span>;
  <span class="synType">double</span> e, f, e_max;
  <span class="synType">float</span> range[] = { <span class="synConstant">0</span>, <span class="synConstant">256</span> };
  <span class="synType">float</span> *ranges[] = { range };
  CvHistogram *hist;

  hist = cvCreateHist(<span class="synConstant">1</span>, &#38;hist_size, CV_HIST_ARRAY, <span class="synConstant">0</span>, <span class="synConstant">1</span>); <span class="synComment">/* ヒストグラムを生成する */</span>

  f = <span class="synConstant">1.0</span> / (w_size*w_size);
  e_max = f * log(f) * w_size * w_size; <span class="synComment">/* エントロピーの最大値 */</span>

  <span class="synStatement">for</span>(i=<span class="synConstant">0</span>; i&#60;src-&#62;height; i++){
    <span class="synStatement">for</span>(j=<span class="synConstant">0</span>; j&#60;src-&#62;width; j++){
      cvSetImageROI(src, cvRect(j, i, w_size, w_size)); <span class="synComment">/* ROIをセット */</span>
      cvCalcHist(&#38;src, hist, <span class="synConstant">0</span>, <span class="synConstant">NULL</span>); <span class="synComment">/* ヒストグラムを計算する */</span>
      <span class="synComment">/* エントロピーの計算 */</span>
      e = <span class="synConstant">0.0</span>;
      <span class="synStatement">for</span>(k=<span class="synConstant">0</span>; k&#60;<span class="synConstant">256</span>; k++){
        <span class="synStatement">if</span>(f = cvQueryHistValue_1D(hist, k)){
          f /= w_size*w_size;
          e += f * log(f);
        }
      }
      dst-&#62;imageData[dst-&#62;widthStep * i + j] = e/e_max*<span class="synConstant">255</span>; <span class="synComment">/* 0〜255で正規化して格納 */</span>
    }
  }

  cvResetImageROI(src); <span class="synComment">/* ROIの解除 */</span>
  cvReleaseHist(&#38;hist); <span class="synComment">/* ヒストグラムを解放する */</span>

  <span class="synStatement">return</span>;
}
</pre>

<p>入力画像</p>
<p><a href="http://f.hatena.ne.jp/Glass_saga/20110602165023" class="hatena-fotolife" target="_blank"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/G/Glass_saga/20110602/20110602165023.jpg" alt="f:id:Glass_saga:20110602165023j:image" title="f:id:Glass_saga:20110602165023j:image" class="hatena-fotolife"></a></p>
<p>結果</p>
<p><a href="http://f.hatena.ne.jp/Glass_saga/20110602165024" class="hatena-fotolife" target="_blank"><img src="http://cdn-ak.f.st-hatena.com/images/fotolife/G/Glass_saga/20110602/20110602165024.jpg" alt="f:id:Glass_saga:20110602165024j:image" title="f:id:Glass_saga:20110602165024j:image" class="hatena-fotolife"></a></p>
</div>
]]></content:encoded>
<dc:creator>Glass_saga</dc:creator>
<dc:date>2011-06-01T12:55:29+09:00</dc:date>
<dc:subject>OpenCV</dc:subject>
</item>
</rdf:RDF>

