SlideShare ist ein Scribd-Unternehmen logo
1 von 45
Downloaden Sie, um offline zu lesen
拡張ライブラリ作成による高速化




   城 一統
自己紹介
●
  城 一統
●
  いとおちゃん
● @i315


●
  高校にいけるか微妙なので応募資格を
  失う前に応募したら言語組受かった
●
  おめでとうございます
そもそも
個別課題
第1希望: CTF
 第2希望:
 文法ハック
 第3希望:
可視化・可聴化
その結果
拡張ライブラリ作成による高速化
     に選ばれた
こんなの
希望してない
希望に入れてないの
に勝手に決められた
竹迫さんが責任を取
ると言って強制的に
 ライブラリ作りへ
何を作ったか
文字列の中でbitが1に
なっている数を超高
   速に数える
  (PopCount)
なんだそれ
だいたいPopCountって
  なんだ!!!!
例


 “A”.bytes.to_a[0] # => 65

65.to_s(2) # => “1000010”

“100010”.count(“1”) # => 2
そもそもそれで
何ができるのですか
何かいいことは
あるのだろうか
画像認識とかその辺
  で便利らしい
(ソースは竹迫さん)
まずやったこと
String#each_char
def popcount_each_char
  count = 0
  self.bytes.each do |byte|
     byte.to_s(2).each_char do |
bit|
       count += 1 if bit == "1"
     end
  end
end
遅い
String#count
知りませんでした
mapしてString#count
def popcount_count
  arr = self.bytes.map do |
byte|
    byte.to_s(2)
  end
  return
arr.join.count("1")
end
そうだ
Hashに入れてみよう
Hashで
   def popcount_hash
     hash = {'x00' => 0, 'x01'       => 1, 'x02' => 1, 'x03' => 2, 'x04' => 1, 'x05' => 2, 'x06' =>
2, 'a' => 3, 'b' => 1, 't' => 2, 'n' => 2, 'v' => 3, 'f' => 2, 'r' => 3, 'x0E' => 3, 'x0F'
 => 4, 'x10' => 1, 'x11' => 2, 'x12' => 2, 'x13' => 3, 'x14' => 2, 'x15' => 3, 'x16' => 3, 'x17' =>
4, 'x18' => 2, 'x19' => 3, 'x1A' => 3, 'e' => 4, 'x1C' => 3, 'x1D' => 4, 'x1E' => 4,
'x1F' => 5, ' ' => 1, '!' => 2, '"' => 2, '#' => 3, '$' => 2, '%' => 3, '&' => 3, ''' => 4, '(' => 2, ')'
=> 3, '*' => 3, '+' => 4, ',' => 3, '-' => 4, '.' => 4, '/' => 5, '0' => 2, '1' => 3, '2' =>
 3, '3' => 4, '4' => 3, '5' => 4, '6' => 4, '7' => 5, '8' => 3, '9' => 4, ':' => 4, ';' => 5, '<' => 4, '='
=> 5, '>' => 5, '?' => 6, '@' => 1, 'A' => 2, 'B' => 2, 'C' => 3, 'D' => 2, 'E' => 3, 'F'
=>
 3, 'G' => 4, 'H' => 2, 'I' => 3, 'J' => 3, 'K' => 4, 'L' => 3, 'M' => 4, 'N' => 4, 'O' => 5, 'P' => 2, 'Q'
=> 3, 'R' => 3, 'S' => 4, 'T' => 3, 'U' => 4, 'V' => 4, 'W' => 5, 'X' => 3, 'Y' => 4, 'Z' =>
 4, '[' => 5, '' => 4, ']' => 5, '^' => 5, '_' => 6, '`' => 2, 'a' => 3, 'b' => 3, 'c' => 4, 'd' => 3, 'e'
=> 4, 'f' => 4, 'g' => 5, 'h' => 3, 'i' => 4, 'j' => 4, 'k' => 5, 'l' => 4, 'm' => 5, 'n' =
> 5, 'o' => 6, 'p' => 3, 'q' => 4, 'r' => 4, 's' => 5, 't' => 4, 'u' => 5, 'v' => 5, 'w' => 6, 'x' => 4, 'y'
=> 5, 'z' => 5, '{' => 6, '|' => 5, '}' => 6, '~' => 6, 'x7F' => 7, 'x80' => 1, … , "xFE"=>7, "xFF"=>8}

      # ↑ココ重要
     count = 0
     self.each_char do |char|
       count += hash[char]
     end
     return count
   end
これはそこそこ速いです
別にHashでやる必要
      はなくて
String#each_byteで
Arrayから持ってきた
ほうが速くね?とい
うツッコミを頂いた
それもそうですね
String#each_byteしてArrayから
def popcount_array
  array = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2,
2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3,
4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3,
4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4,
4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3,
, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4,
5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5,
5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3,
4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6,
6, 7, 6, 7, 7, 8]
  count = 0
  self.each_byte do |byte|
    count += array[byte]
  end
  return count
end
いろいろとひどいけ
 どこれが結構速い
How to use
str = ”takesako”
str.popcount
# => 36
ベンチマーク
bench.rb
require “benchmark” …


arr = ["t", "a", "k", "e", "s", "a", "k", "o"]
str = ""
50000.times do
  str << arr.shuffle.join
end
Benchmark.bm do |x|
  bench_each_char = x.report("each_char:") do
    10.times do
      str.popcount_each_char
    end
  end
  bench_count = ...
  bench_hash = ...
  bench_array = …
  bench_c = ...
  bench_c_cpu = …
end
結果


% ruby bench.rb

           user      system      total            real
each_char: 10.630000    0.020000 10.650000    (   10.632659)
count:      2.040000    0.050000   2.090000   (    2.094404)
hash:       1.120000    0.010000   1.130000   (    1.137357)
array:      0.380000    0.000000   0.380000   (    0.379857)
これは速い
そしてこれを
Cで書いてみた
popcount.c
#include <ruby.h>

VALUE popcount_m(VALUE);
VALUE popcount_cpu_m(VALUE);

void Init_popcount(void) {
   VALUE cString = rb_define_class("String",
rb_cObject);
   rb_define_method(cString, "popcount", popcount_m,
0);
   rb_define_method(cString, "popcount_cpu",
popcount_cpu_m, 0);
}
VALUE popcount_m(VALUE self) { … }
VALUE popcount_cpu_m(VALUE self) { … }
VALUE popcount_m(VALUE self)
VALUE popcount_m(VALUE self) {
  int count = 0;
  int i;
  char *ptr;
     static int array[256] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2,
3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2,
2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3,
4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5,
6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
     ptr = RSTRING_PTR(self);
     for (i = 0; i < RSTRING_LEN(self); i++) {
         count += array[ptr[i]];
     }
     return INT2FIX(count);
}
VALUE popcount_cpu_m(VALUE)

VALUE popcount_cpu_m(VALUE self) {
  int count = 0;
  int i;
  long long *ptrll;

    ptrll = (long long *)RSTRING_PTR(self);
    for (i = 0; i < RSTRING_LEN(self); i += sizeof(long long)) {
        count += __builtin_popcountll(*ptrll++);
    }
    return INT2FIX(count);
}
ベンチマーク
% ruby bench.rb

           user       system     total      real
each_char: 8.100000   0.000000   8.100000   ( 8.120804)
count:     1.470000   0.200000   1.670000   ( 1.680836)
hash:      0.800000   0.000000   0.800000   ( 0.802213)
array:     0.310000   0.000000   0.310000   ( 0.308227)
c:         0.000000   0.000000   0.000000   ( 0.003734)
c_cpu:     0.000000   0.000000   0.000000   ( 0.000474)


Cで書いたものがRubyで書いた
ものより2桁程度高速化して
Cで書いてPOPCNT命令を使用し
たものがさらに1桁高速化
速い!!!!!
正直速くても
自分は使いそう
 にないので
わりとどうでも
   いい
少なくとも僕は
使い道が全くわ
 かりません
まとめ
●   Rubyはちょっとしたさほど負荷のかからない
    処理なら他の言語と比べても実用的なレベル
●
    負荷のかかることをやるとどうしても差が出る
●   誰かRubyをもっと速くしてください
ご清聴ありがと
うございました

Weitere ähnliche Inhalte

Was ist angesagt?

知ってるようで意外と知らないPHPの便利関数
知ってるようで意外と知らないPHPの便利関数知ってるようで意外と知らないPHPの便利関数
知ってるようで意外と知らないPHPの便利関数Wataru Terada
 
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロdigitalghost
 
Boost.Preprocessorでプログラミングしましょう
Boost.PreprocessorでプログラミングしましょうBoost.Preprocessorでプログラミングしましょう
Boost.Preprocessorでプログラミングしましょうdigitalghost
 
Ext.Directについて
Ext.DirectについてExt.Directについて
Ext.DirectについてYuki Naotori
 
データサイエンティストに聞く!今更聞けない機械学習の基礎から応用まで V6
データサイエンティストに聞く!今更聞けない機械学習の基礎から応用まで V6データサイエンティストに聞く!今更聞けない機械学習の基礎から応用まで V6
データサイエンティストに聞く!今更聞けない機械学習の基礎から応用まで V6Shunsuke Nakamura
 

Was ist angesagt? (6)

知ってるようで意外と知らないPHPの便利関数
知ってるようで意外と知らないPHPの便利関数知ってるようで意外と知らないPHPの便利関数
知ってるようで意外と知らないPHPの便利関数
 
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
 
Boost.Preprocessorでプログラミングしましょう
Boost.PreprocessorでプログラミングしましょうBoost.Preprocessorでプログラミングしましょう
Boost.Preprocessorでプログラミングしましょう
 
Ext.Directについて
Ext.DirectについてExt.Directについて
Ext.Directについて
 
データサイエンティストに聞く!今更聞けない機械学習の基礎から応用まで V6
データサイエンティストに聞く!今更聞けない機械学習の基礎から応用まで V6データサイエンティストに聞く!今更聞けない機械学習の基礎から応用まで V6
データサイエンティストに聞く!今更聞けない機械学習の基礎から応用まで V6
 
MT meets PHP
MT meets PHPMT meets PHP
MT meets PHP
 

Ähnlich wie 拡張ライブラリ作成による高速化

R's anti sparseness
R's anti sparsenessR's anti sparseness
R's anti sparsenessybenjo
 
競技プログラミング練習会2015 Normal 第1回
競技プログラミング練習会2015 Normal 第1回競技プログラミング練習会2015 Normal 第1回
競技プログラミング練習会2015 Normal 第1回Hideaki Nagamine
 
Operations research yonezawa_no2
Operations research yonezawa_no2Operations research yonezawa_no2
Operations research yonezawa_no2ssuser0bebd2
 
MT meets PHP - PHP conference Kansai 2013
MT meets PHP - PHP conference Kansai 2013MT meets PHP - PHP conference Kansai 2013
MT meets PHP - PHP conference Kansai 2013純生 野田
 
バシク行列システムの解説 2版
バシク行列システムの解説 2版バシク行列システムの解説 2版
バシク行列システムの解説 2版Bashicu Hyudora
 
Facebook, LinkedIN & Beyond - or how the new media changed how sales people d...
Facebook, LinkedIN & Beyond - or how the new media changed how sales people d...Facebook, LinkedIN & Beyond - or how the new media changed how sales people d...
Facebook, LinkedIN & Beyond - or how the new media changed how sales people d...AdNerds
 
Rデモ03_データ分析編2016
Rデモ03_データ分析編2016Rデモ03_データ分析編2016
Rデモ03_データ分析編2016wada, kazumi
 
Fblinkedinbeyondv01 1234514863232782 1
Fblinkedinbeyondv01 1234514863232782 1Fblinkedinbeyondv01 1234514863232782 1
Fblinkedinbeyondv01 1234514863232782 1guestcaceba
 
レベルを上げて物理で殴れ、Fuzzing入門 #pyfes
レベルを上げて物理で殴れ、Fuzzing入門 #pyfesレベルを上げて物理で殴れ、Fuzzing入門 #pyfes
レベルを上げて物理で殴れ、Fuzzing入門 #pyfesTokoroten Nakayama
 
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列Taketo Sano
 
Write good parser in perl
Write good parser in perlWrite good parser in perl
Write good parser in perlJiro Nishiguchi
 
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~leverages_event
 
㉗HTML5+jQueryでお絵かき
㉗HTML5+jQueryでお絵かき㉗HTML5+jQueryでお絵かき
㉗HTML5+jQueryでお絵かきNishida Kansuke
 
MySQLerの7つ道具
MySQLerの7つ道具MySQLerの7つ道具
MySQLerの7つ道具yoku0825
 
Web APIを用いたプレイリスト検索機能.pdf
Web APIを用いたプレイリスト検索機能.pdfWeb APIを用いたプレイリスト検索機能.pdf
Web APIを用いたプレイリスト検索機能.pdfssuser30e599
 
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~Nobuhisa Koizumi
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるShintaro Fukushima
 
KMC JavaScriptから始めるプログラミング2016 第一回
KMC JavaScriptから始めるプログラミング2016 第一回KMC JavaScriptから始めるプログラミング2016 第一回
KMC JavaScriptから始めるプログラミング2016 第一回kyoto university
 

Ähnlich wie 拡張ライブラリ作成による高速化 (20)

R's anti sparseness
R's anti sparsenessR's anti sparseness
R's anti sparseness
 
競技プログラミング練習会2015 Normal 第1回
競技プログラミング練習会2015 Normal 第1回競技プログラミング練習会2015 Normal 第1回
競技プログラミング練習会2015 Normal 第1回
 
Operations research yonezawa_no2
Operations research yonezawa_no2Operations research yonezawa_no2
Operations research yonezawa_no2
 
Tokyo r33 beginner
Tokyo r33 beginnerTokyo r33 beginner
Tokyo r33 beginner
 
MT meets PHP - PHP conference Kansai 2013
MT meets PHP - PHP conference Kansai 2013MT meets PHP - PHP conference Kansai 2013
MT meets PHP - PHP conference Kansai 2013
 
バシク行列システムの解説 2版
バシク行列システムの解説 2版バシク行列システムの解説 2版
バシク行列システムの解説 2版
 
Facebook, LinkedIN & Beyond - or how the new media changed how sales people d...
Facebook, LinkedIN & Beyond - or how the new media changed how sales people d...Facebook, LinkedIN & Beyond - or how the new media changed how sales people d...
Facebook, LinkedIN & Beyond - or how the new media changed how sales people d...
 
Rデモ03_データ分析編2016
Rデモ03_データ分析編2016Rデモ03_データ分析編2016
Rデモ03_データ分析編2016
 
Fblinkedinbeyondv01 1234514863232782 1
Fblinkedinbeyondv01 1234514863232782 1Fblinkedinbeyondv01 1234514863232782 1
Fblinkedinbeyondv01 1234514863232782 1
 
Apostida de torneamento
Apostida de torneamentoApostida de torneamento
Apostida de torneamento
 
レベルを上げて物理で殴れ、Fuzzing入門 #pyfes
レベルを上げて物理で殴れ、Fuzzing入門 #pyfesレベルを上げて物理で殴れ、Fuzzing入門 #pyfes
レベルを上げて物理で殴れ、Fuzzing入門 #pyfes
 
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
プログラマのための線形代数再入門2 〜 要件定義から学ぶ行列式と逆行列
 
Write good parser in perl
Write good parser in perlWrite good parser in perl
Write good parser in perl
 
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
 
㉗HTML5+jQueryでお絵かき
㉗HTML5+jQueryでお絵かき㉗HTML5+jQueryでお絵かき
㉗HTML5+jQueryでお絵かき
 
MySQLerの7つ道具
MySQLerの7つ道具MySQLerの7つ道具
MySQLerの7つ道具
 
Web APIを用いたプレイリスト検索機能.pdf
Web APIを用いたプレイリスト検索機能.pdfWeb APIを用いたプレイリスト検索機能.pdf
Web APIを用いたプレイリスト検索機能.pdf
 
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみる
 
KMC JavaScriptから始めるプログラミング2016 第一回
KMC JavaScriptから始めるプログラミング2016 第一回KMC JavaScriptから始めるプログラミング2016 第一回
KMC JavaScriptから始めるプログラミング2016 第一回
 

拡張ライブラリ作成による高速化