SlideShare une entreprise Scribd logo
1  sur  22
Télécharger pour lire hors ligne
Rのデータ構造とメモリ管理
    一人 R 勉強会 #1 (2012/11/25)
                    @a_bicky


             2012/12/15 改訂版
自己紹介

• Takeshi Arabiki
   ‣   Web 業界の底辺エンジニア

   ‣ Twitter & はてな: @a_bicky & id:a_bicky

• 興味など
  機械学習、自然言語処理、R

• ブログ
  あらびき日記 http://d.hatena.ne.jp/a_bicky/
R関係の主な発表

      Tokyo.R #16                               Tsukuba.R #9                             Rユーザ会 2011




http://www.slideshare.net/abicky/r-9034336 http://www.slideshare.net/abicky/r-10128090 http://www.slideshare.net/abicky/rtwitter
注意事項


 C 言語書けません&読めません
そんな エンジニアのメモ書きです
 間違いは @a_bicky 宛に連絡していただけると喜びます
Rのデータ構造
2つのデータ構造
    SEXPREC

たぶん Symbolic EXPression RECord (S-EXPression RECord) の略
*SEXP = SEXPREC
VECTOR_SEXPREC 以外のノード(オブジェクト)


VECTOR_SEXPREC

SEXPREC の Vector 版(メモリを少し節約)
*VECSEXP = VECTOR_SEXPREC
データ部分は直後のアドレスに格納
raw, logical, integer, numeric, complex, character, list, expression 等
SEXPREC
// cf. src/include/Rinternals.h
typedef struct SEXPREC {
  struct sxpinfo_struct sxpinfo;     //   詳細は後述
  struct SEXPREC *attrib;            //   属性情報
  struct SEXPREC *gengc_next_node;   //   GC で使用
  struct SEXPREC *gengc_prev_node;   //   GC で使用
  // データ部分
  union {
    struct primsxp_struct primsxp;
    struct symsxp_struct symsxp;
    struct listsxp_struct listsxp;
    struct envsxp_struct envsxp;
    struct closxp_struct closxp;
    struct promsxp_struct promsxp;
  } u;
} SEXPREC, *SEXP;
VECTOR_SEXPREC
// cf. src/include/Rinternals.h
typedef struct VECTOR_SEXPREC {
  struct sxpinfo_struct sxpinfo;   // 詳細は後述
  struct SEXPREC *attrib;          // 属性情報
  struct SEXPREC *gengc_next_node; // GC で使用
  struct SEXPREC *gengc_prev_node; // GC で使用
  struct vecsxp_struct vecsxp; // length, truelength
} VECTOR_SEXPREC, *VECSEXP;

// データ部分のアライメントをするための変数?
typedef union {
  VECTOR_SEXPREC s;
  double align; } SEXPREC_ALIGN;

// データ部分の先頭アドレスの定義
#define DATAPTR(x)	 (((SEXPREC_ALIGN *) (x)) + 1)
VECTOR_SEXPREC
          VECTOR_SEXPREC のイメージ

                                     VECTOR_SEXPREC

ノード
sxpinfo               attrib       gengc_next_node
gengc_prev_node    vecsxp_struct

          データ部分 sizeof(VECREC) * length
sxpinfo_struct
// cf. src/include/Rinternals.h
struct sxpinfo_struct {
   SEXPTYPE type      : 5; // ノードのタイプ
   unsigned int obj   : 1;
   unsigned int named : 2; // コピーの際の挙動を制御
   unsigned int gp    : 16;
   unsigned int mark : 1; // Mark-and-Sweap の mark
   unsigned int debug : 1;
   unsigned int trace : 1; // tracemem 等で使用
   unsigned int spare : 1; // もう使われていないらしい
   unsigned int gcgen : 1; // GC の世代情報
   unsigned int gccls : 3; // サイズに応じたクラス番号
};
Rのメモリ管理
基礎知識
• メモリ管理の上でノードは3種類に分かれる
 ‣   non-vector (gccls = 0)

 ‣   small vector(gccls = 1, 2, 3, 4, 5, 6)

 ‣   large vector (gccls = 7)

• GC は世代別 GC
 ‣   old 世代は gcgen = 0, 1 の2つ存在

 ‣   old 世代からより若い世代への参照は参照が発生する度
     にリストに追加する形で管理(デフォルトオプション)
R の世代別 GC
           各世代は双方向リストとなっている
           → 挿入・削除を定数時間で行える
   R_GenHeap[gccls].New                  R_GenHeap[gccls].Old[gen]
= &R_GenHeap[gccls].NewPeg            = &R_GenHeap[gccls].OldPeg[gen]


                    gengc_prev_node

                      gengc_next_node



  node3           node1


                                          node2        node1
          node2
                                               gen th
 New generation                           Old generation
R の世代別 GC の手順
1. old 世代のうち何番目の世代までを GC 対象とするか決定

2. GC 対象の old 世代から参照されているノードを参照元世代に移す

3. GC 対象の old 世代の世代 (gcgen) をインクリメントして unmark
   した上で new 世代に移す

4. GC 対象外の old 世代から参照されているノードを mark し old 世
   代に移す

5. root からたどって参照のあるノードを mark し old 世代に移す

6. large vector の new 世代に存在するノードを解放

7. 場合によっては non-vector, small vector のうち unmarked な
   ノードを解放

cf. RunGenCollect (src/main/memory.c)
gc 関数の結果の意味
> gc()  # 全世代を対象とした GC (full GC)
         used (Mb) gc trigger (Mb) max used (Mb)
Ncells 180515 9.7      407500 21.8   350000 18.7
Vcells 287939 2.2      905753 7.0    877008 6.7


                  used                      Mb
         使用中のノードの数。                sizeof(SEXPREC) x
         non-vector, small         ノードの数 / 1024 /
Ncells
         vector, large vecotor 全   1024
         てを含む。
         全 vector ノードのデータ          ← を個数ではなく Mb で
         部分(ヘッダ部分を除                表した値。
Vcells
         く)が VECREC 何個分の           つまり sizeof(VECREC)
         サイズに相当するか                 x 個数 / 1024 / 1024
メモリ確保の仕組み
• small vector
 1. データ部分のサイズが VECREC 何個分相当かを算出

 2. 1 の結果が1以下であれば gccls = 1、2以下は2、4以下は3、6
    以下は4、8以下は5、16以下は6という具合に gccls をセット

 3. 対応する gccls の使用されていないノードを割り当てる

 4. 使用されていないノードが存在しない場合は一定量のノードを新
    しく生成 (GetNewPage)


• non-vector
 ‣   ↑の手順のうち gccls を 0 とする
メモリ確保の仕組み
• large vector
 1. データ部分のサイズが VECREC 何個分相当かを算出

 2. 1 の結果が16より大きければ gccls を 7 にセット

 3. 必要なサイズをその都度 malloc で確保




いずれの場合もメモリが足りない場合は GC を実行したり
ヒープサイズを調整する
tracemem の仕組み
// cf. src/main/duplicate.c
SEXP duplicate(SEXP s){
  SEXP t;

    duplicate_counter++;
    t = duplicate1(s);
    // (s)->sxpinfo.trace フラグが立っていればレポートを出力
    if (RTRACE(s) && !(TYPEOF(s) == CLOSXP     ||
                       TYPEOF(s) == BUILTINSXP ||
                       TYPEOF(s) == SPECIALSXP ||
                       TYPEOF(s) == PROMSXP    ||
                       TYPEOF(s) == ENVSXP)){
      memtrace_report(s,t);
      // コピーしたノードにもフラグを立てる
      SET_RTRACE(t,1);
    }
    return t;
}
tracemem の挙動
duplicate が呼ばれないコピーはトレースできない

> tracemem(a <- 1:5)
[1] "<0x103011a48>"
> b <- a
> b[1] <- 1 # そのまま代入した場合はトレースされる
tracemem[0x103011a48 -> 0x101b41760]:
tracemem[0x101b41760 -> 0x103063188]:
> c <- a[1:5]
> c[1] <- 1 # インデックスを指定した場合はトレースされない
> tracemem(a <- list(a = 1:5))
[1] "<0x1064c0958>"
> b <- a
> a$a <- 1   # そのまま代入した場合はトレースされる
tracemem[0x1064c0958 -> 0x1067e9598]:
> c <- a$a
> c[1] <- 1 # 一部の要素の代入はトレースされない
終
参考文献

•   R Internals - 1.1 SEXPs
    http://cran.r-project.org/doc/manuals/R-ints.html#SEXPs

•   RObjectModel - r-optimization-engine - Optimizing the
    performance of R - Google Project Hosting
    http://code.google.com/p/r-optimization-engine/wiki/
    RObjectModel

•   R 2.15.2 のソースコード
    主に src/include/Rinternals.h, src/main/include/Defn.h,
    src/main/memory.c
変更履歴
•   2012/12/15
    世代別 GC の旧世代の世代数が2なのに3になっていたのを訂正

Contenu connexe

Tendances

統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用Shintaro Fukushima
 
mmapパッケージを使ってお手軽オブジェクト管理
mmapパッケージを使ってお手軽オブジェクト管理mmapパッケージを使ってお手軽オブジェクト管理
mmapパッケージを使ってお手軽オブジェクト管理Shintaro Fukushima
 
Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Shintaro Fukushima
 
Rユーザのためのspark入門
Rユーザのためのspark入門Rユーザのためのspark入門
Rユーザのためのspark入門Shintaro Fukushima
 
for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力imuyaoti
 
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」Nagi Teramo
 
Why dont you_create_new_spark_jl
Why dont you_create_new_spark_jlWhy dont you_create_new_spark_jl
Why dont you_create_new_spark_jlShintaro Fukushima
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるShintaro Fukushima
 
Feature Selection with R / in JP
Feature Selection with R / in JPFeature Selection with R / in JP
Feature Selection with R / in JPSercan Ahi
 
TensorFlow White Paperを読む
TensorFlow White Paperを読むTensorFlow White Paperを読む
TensorFlow White Paperを読むYuta Kashino
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxpsMITSUNARI Shigeo
 
PythonでテキストをJSONにした話(PyCon mini sapporo 2015)
PythonでテキストをJSONにした話(PyCon mini sapporo 2015)PythonでテキストをJSONにした話(PyCon mini sapporo 2015)
PythonでテキストをJSONにした話(PyCon mini sapporo 2015)Satoshi Yamada
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装MITSUNARI Shigeo
 
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014Takashi J OZAKI
 
Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介MITSUNARI Shigeo
 
Rが苦手な人にもRを使って頂くために~RcommanderとRook~
Rが苦手な人にもRを使って頂くために~RcommanderとRook~Rが苦手な人にもRを使って頂くために~RcommanderとRook~
Rが苦手な人にもRを使って頂くために~RcommanderとRook~Kazuya Wada
 

Tendances (20)

統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
 
Tokyo.R#16 wdkz
Tokyo.R#16 wdkzTokyo.R#16 wdkz
Tokyo.R#16 wdkz
 
mmapパッケージを使ってお手軽オブジェクト管理
mmapパッケージを使ってお手軽オブジェクト管理mmapパッケージを使ってお手軽オブジェクト管理
mmapパッケージを使ってお手軽オブジェクト管理
 
Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)
 
Rユーザのためのspark入門
Rユーザのためのspark入門Rユーザのためのspark入門
Rユーザのためのspark入門
 
for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力
 
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
「plyrパッケージで君も前処理スタ☆」改め「plyrパッケージ徹底入門」
 
Why dont you_create_new_spark_jl
Why dont you_create_new_spark_jlWhy dont you_create_new_spark_jl
Why dont you_create_new_spark_jl
 
Prosym2012
Prosym2012Prosym2012
Prosym2012
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみる
 
Feature Selection with R / in JP
Feature Selection with R / in JPFeature Selection with R / in JP
Feature Selection with R / in JP
 
TensorFlow White Paperを読む
TensorFlow White Paperを読むTensorFlow White Paperを読む
TensorFlow White Paperを読む
 
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
 
PythonでテキストをJSONにした話(PyCon mini sapporo 2015)
PythonでテキストをJSONにした話(PyCon mini sapporo 2015)PythonでテキストをJSONにした話(PyCon mini sapporo 2015)
PythonでテキストをJSONにした話(PyCon mini sapporo 2015)
 
LLVM最適化のこつ
LLVM最適化のこつLLVM最適化のこつ
LLVM最適化のこつ
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装
 
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
 
llvm入門
llvm入門llvm入門
llvm入門
 
Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介
 
Rが苦手な人にもRを使って頂くために~RcommanderとRook~
Rが苦手な人にもRを使って頂くために~RcommanderとRook~Rが苦手な人にもRを使って頂くために~RcommanderとRook~
Rが苦手な人にもRを使って頂くために~RcommanderとRook~
 

Similaire à Rのデータ構造とメモリ管理

ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!Yohei Fushii
 
tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1Ryosuke IWANAGA
 
これからのコンピューティングとJava(Hacker Tackle)
これからのコンピューティングとJava(Hacker Tackle)これからのコンピューティングとJava(Hacker Tackle)
これからのコンピューティングとJava(Hacker Tackle)なおき きしだ
 
ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。Kazuki Onishi
 
並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.jsYoshiiro Ueno
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)Takeshi Yamamuro
 
コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道なおき きしだ
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, CodereadingHiro Yoshioka
 
20181212 - PGconf.ASIA - LT
20181212 - PGconf.ASIA - LT20181212 - PGconf.ASIA - LT
20181212 - PGconf.ASIA - LTKohei KaiGai
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another sideKiwamu Okabe
 
【関東GPGPU勉強会#4】GTX 1080でComputer Vision アルゴリズムを色々動かしてみる
【関東GPGPU勉強会#4】GTX 1080でComputer Visionアルゴリズムを色々動かしてみる【関東GPGPU勉強会#4】GTX 1080でComputer Visionアルゴリズムを色々動かしてみる
【関東GPGPU勉強会#4】GTX 1080でComputer Vision アルゴリズムを色々動かしてみるYasuhiro Yoshimura
 
NVIDIA Japan Seminar 2012
NVIDIA Japan Seminar 2012NVIDIA Japan Seminar 2012
NVIDIA Japan Seminar 2012Takuro Iizuka
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenMITSUNARI Shigeo
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1信之 岩永
 

Similaire à Rのデータ構造とメモリ管理 (20)

about dakota6.7 gui
about dakota6.7 guiabout dakota6.7 gui
about dakota6.7 gui
 
ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!
 
tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1
 
これからのコンピューティングとJava(Hacker Tackle)
これからのコンピューティングとJava(Hacker Tackle)これからのコンピューティングとJava(Hacker Tackle)
これからのコンピューティングとJava(Hacker Tackle)
 
HPC Phys-20201203
HPC Phys-20201203HPC Phys-20201203
HPC Phys-20201203
 
ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。
 
並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道
 
about DakotagUI
about DakotagUIabout DakotagUI
about DakotagUI
 
20130819 jjugnslt
20130819 jjugnslt20130819 jjugnslt
20130819 jjugnslt
 
仮想記憶の構築法
仮想記憶の構築法仮想記憶の構築法
仮想記憶の構築法
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, Codereading
 
Maatkitの紹介
Maatkitの紹介Maatkitの紹介
Maatkitの紹介
 
20181212 - PGconf.ASIA - LT
20181212 - PGconf.ASIA - LT20181212 - PGconf.ASIA - LT
20181212 - PGconf.ASIA - LT
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another side
 
【関東GPGPU勉強会#4】GTX 1080でComputer Vision アルゴリズムを色々動かしてみる
【関東GPGPU勉強会#4】GTX 1080でComputer Visionアルゴリズムを色々動かしてみる【関東GPGPU勉強会#4】GTX 1080でComputer Visionアルゴリズムを色々動かしてみる
【関東GPGPU勉強会#4】GTX 1080でComputer Vision アルゴリズムを色々動かしてみる
 
NVIDIA Japan Seminar 2012
NVIDIA Japan Seminar 2012NVIDIA Japan Seminar 2012
NVIDIA Japan Seminar 2012
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1
 

Plus de Takeshi Arabiki

クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜Takeshi Arabiki
 
Introduction to Japanese Morphological Analysis
Introduction to Japanese Morphological AnalysisIntroduction to Japanese Morphological Analysis
Introduction to Japanese Morphological AnalysisTakeshi Arabiki
 
R による文書分類入門
R による文書分類入門R による文書分類入門
R による文書分類入門Takeshi Arabiki
 
HTML5 Canvas で学ぶアフィン変換
HTML5 Canvas で学ぶアフィン変換HTML5 Canvas で学ぶアフィン変換
HTML5 Canvas で学ぶアフィン変換Takeshi Arabiki
 
Introduction to Favmemo for Immature Engineers
Introduction to Favmemo for Immature EngineersIntroduction to Favmemo for Immature Engineers
Introduction to Favmemo for Immature EngineersTakeshi Arabiki
 
Rのスコープとフレームと環境と
Rのスコープとフレームと環境とRのスコープとフレームと環境と
Rのスコープとフレームと環境とTakeshi Arabiki
 
twitteRで快適Rライフ!
twitteRで快適Rライフ!twitteRで快適Rライフ!
twitteRで快適Rライフ!Takeshi Arabiki
 
RではじめるTwitter解析
RではじめるTwitter解析RではじめるTwitter解析
RではじめるTwitter解析Takeshi Arabiki
 
R版Getopt::Longを作ってみた
R版Getopt::Longを作ってみたR版Getopt::Longを作ってみた
R版Getopt::Longを作ってみたTakeshi Arabiki
 
Rデータフレーム自由自在
Rデータフレーム自由自在Rデータフレーム自由自在
Rデータフレーム自由自在Takeshi Arabiki
 
文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜
文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜
文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜Takeshi Arabiki
 
Rデバッグあれこれ
RデバッグあれこれRデバッグあれこれ
RデバッグあれこれTakeshi Arabiki
 
はじめてのまっぷりでゅ〜す
はじめてのまっぷりでゅ〜すはじめてのまっぷりでゅ〜す
はじめてのまっぷりでゅ〜すTakeshi Arabiki
 
TwitterのデータをRであれこれ
TwitterのデータをRであれこれTwitterのデータをRであれこれ
TwitterのデータをRであれこれTakeshi Arabiki
 
Twitterのデータを取得する準備
Twitterのデータを取得する準備Twitterのデータを取得する準備
Twitterのデータを取得する準備Takeshi Arabiki
 

Plus de Takeshi Arabiki (17)

開発の心得
開発の心得開発の心得
開発の心得
 
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜
 
Introduction to Japanese Morphological Analysis
Introduction to Japanese Morphological AnalysisIntroduction to Japanese Morphological Analysis
Introduction to Japanese Morphological Analysis
 
R による文書分類入門
R による文書分類入門R による文書分類入門
R による文書分類入門
 
HTML5 Canvas で学ぶアフィン変換
HTML5 Canvas で学ぶアフィン変換HTML5 Canvas で学ぶアフィン変換
HTML5 Canvas で学ぶアフィン変換
 
Introduction to Favmemo for Immature Engineers
Introduction to Favmemo for Immature EngineersIntroduction to Favmemo for Immature Engineers
Introduction to Favmemo for Immature Engineers
 
Rのスコープとフレームと環境と
Rのスコープとフレームと環境とRのスコープとフレームと環境と
Rのスコープとフレームと環境と
 
twitteRで快適Rライフ!
twitteRで快適Rライフ!twitteRで快適Rライフ!
twitteRで快適Rライフ!
 
RではじめるTwitter解析
RではじめるTwitter解析RではじめるTwitter解析
RではじめるTwitter解析
 
R版Getopt::Longを作ってみた
R版Getopt::Longを作ってみたR版Getopt::Longを作ってみた
R版Getopt::Longを作ってみた
 
Rデータフレーム自由自在
Rデータフレーム自由自在Rデータフレーム自由自在
Rデータフレーム自由自在
 
HMM, MEMM, CRF メモ
HMM, MEMM, CRF メモHMM, MEMM, CRF メモ
HMM, MEMM, CRF メモ
 
文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜
文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜
文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜
 
Rデバッグあれこれ
RデバッグあれこれRデバッグあれこれ
Rデバッグあれこれ
 
はじめてのまっぷりでゅ〜す
はじめてのまっぷりでゅ〜すはじめてのまっぷりでゅ〜す
はじめてのまっぷりでゅ〜す
 
TwitterのデータをRであれこれ
TwitterのデータをRであれこれTwitterのデータをRであれこれ
TwitterのデータをRであれこれ
 
Twitterのデータを取得する準備
Twitterのデータを取得する準備Twitterのデータを取得する準備
Twitterのデータを取得する準備
 

Rのデータ構造とメモリ管理

  • 1. Rのデータ構造とメモリ管理 一人 R 勉強会 #1 (2012/11/25) @a_bicky 2012/12/15 改訂版
  • 2. 自己紹介 • Takeshi Arabiki ‣ Web 業界の底辺エンジニア ‣ Twitter & はてな: @a_bicky & id:a_bicky • 興味など 機械学習、自然言語処理、R • ブログ あらびき日記 http://d.hatena.ne.jp/a_bicky/
  • 3. R関係の主な発表 Tokyo.R #16 Tsukuba.R #9 Rユーザ会 2011 http://www.slideshare.net/abicky/r-9034336 http://www.slideshare.net/abicky/r-10128090 http://www.slideshare.net/abicky/rtwitter
  • 4. 注意事項 C 言語書けません&読めません そんな エンジニアのメモ書きです 間違いは @a_bicky 宛に連絡していただけると喜びます
  • 6. 2つのデータ構造 SEXPREC たぶん Symbolic EXPression RECord (S-EXPression RECord) の略 *SEXP = SEXPREC VECTOR_SEXPREC 以外のノード(オブジェクト) VECTOR_SEXPREC SEXPREC の Vector 版(メモリを少し節約) *VECSEXP = VECTOR_SEXPREC データ部分は直後のアドレスに格納 raw, logical, integer, numeric, complex, character, list, expression 等
  • 7. SEXPREC // cf. src/include/Rinternals.h typedef struct SEXPREC { struct sxpinfo_struct sxpinfo; // 詳細は後述 struct SEXPREC *attrib; // 属性情報 struct SEXPREC *gengc_next_node; // GC で使用 struct SEXPREC *gengc_prev_node; // GC で使用 // データ部分 union { struct primsxp_struct primsxp; struct symsxp_struct symsxp; struct listsxp_struct listsxp; struct envsxp_struct envsxp; struct closxp_struct closxp; struct promsxp_struct promsxp; } u; } SEXPREC, *SEXP;
  • 8. VECTOR_SEXPREC // cf. src/include/Rinternals.h typedef struct VECTOR_SEXPREC { struct sxpinfo_struct sxpinfo; // 詳細は後述 struct SEXPREC *attrib; // 属性情報 struct SEXPREC *gengc_next_node; // GC で使用 struct SEXPREC *gengc_prev_node; // GC で使用 struct vecsxp_struct vecsxp; // length, truelength } VECTOR_SEXPREC, *VECSEXP; // データ部分のアライメントをするための変数? typedef union { VECTOR_SEXPREC s; double align; } SEXPREC_ALIGN; // データ部分の先頭アドレスの定義 #define DATAPTR(x) (((SEXPREC_ALIGN *) (x)) + 1)
  • 9. VECTOR_SEXPREC VECTOR_SEXPREC のイメージ VECTOR_SEXPREC ノード sxpinfo attrib gengc_next_node gengc_prev_node vecsxp_struct データ部分 sizeof(VECREC) * length
  • 10. sxpinfo_struct // cf. src/include/Rinternals.h struct sxpinfo_struct { SEXPTYPE type : 5; // ノードのタイプ unsigned int obj : 1; unsigned int named : 2; // コピーの際の挙動を制御 unsigned int gp : 16; unsigned int mark : 1; // Mark-and-Sweap の mark unsigned int debug : 1; unsigned int trace : 1; // tracemem 等で使用 unsigned int spare : 1; // もう使われていないらしい unsigned int gcgen : 1; // GC の世代情報 unsigned int gccls : 3; // サイズに応じたクラス番号 };
  • 12. 基礎知識 • メモリ管理の上でノードは3種類に分かれる ‣ non-vector (gccls = 0) ‣ small vector(gccls = 1, 2, 3, 4, 5, 6) ‣ large vector (gccls = 7) • GC は世代別 GC ‣ old 世代は gcgen = 0, 1 の2つ存在 ‣ old 世代からより若い世代への参照は参照が発生する度 にリストに追加する形で管理(デフォルトオプション)
  • 13. R の世代別 GC 各世代は双方向リストとなっている → 挿入・削除を定数時間で行える R_GenHeap[gccls].New R_GenHeap[gccls].Old[gen] = &R_GenHeap[gccls].NewPeg = &R_GenHeap[gccls].OldPeg[gen] gengc_prev_node gengc_next_node node3 node1 node2 node1 node2 gen th New generation Old generation
  • 14. R の世代別 GC の手順 1. old 世代のうち何番目の世代までを GC 対象とするか決定 2. GC 対象の old 世代から参照されているノードを参照元世代に移す 3. GC 対象の old 世代の世代 (gcgen) をインクリメントして unmark した上で new 世代に移す 4. GC 対象外の old 世代から参照されているノードを mark し old 世 代に移す 5. root からたどって参照のあるノードを mark し old 世代に移す 6. large vector の new 世代に存在するノードを解放 7. 場合によっては non-vector, small vector のうち unmarked な ノードを解放 cf. RunGenCollect (src/main/memory.c)
  • 15. gc 関数の結果の意味 > gc() # 全世代を対象とした GC (full GC) used (Mb) gc trigger (Mb) max used (Mb) Ncells 180515 9.7 407500 21.8 350000 18.7 Vcells 287939 2.2 905753 7.0 877008 6.7 used Mb 使用中のノードの数。 sizeof(SEXPREC) x non-vector, small ノードの数 / 1024 / Ncells vector, large vecotor 全 1024 てを含む。 全 vector ノードのデータ ← を個数ではなく Mb で 部分(ヘッダ部分を除 表した値。 Vcells く)が VECREC 何個分の つまり sizeof(VECREC) サイズに相当するか x 個数 / 1024 / 1024
  • 16. メモリ確保の仕組み • small vector 1. データ部分のサイズが VECREC 何個分相当かを算出 2. 1 の結果が1以下であれば gccls = 1、2以下は2、4以下は3、6 以下は4、8以下は5、16以下は6という具合に gccls をセット 3. 対応する gccls の使用されていないノードを割り当てる 4. 使用されていないノードが存在しない場合は一定量のノードを新 しく生成 (GetNewPage) • non-vector ‣ ↑の手順のうち gccls を 0 とする
  • 17. メモリ確保の仕組み • large vector 1. データ部分のサイズが VECREC 何個分相当かを算出 2. 1 の結果が16より大きければ gccls を 7 にセット 3. 必要なサイズをその都度 malloc で確保 いずれの場合もメモリが足りない場合は GC を実行したり ヒープサイズを調整する
  • 18. tracemem の仕組み // cf. src/main/duplicate.c SEXP duplicate(SEXP s){ SEXP t; duplicate_counter++; t = duplicate1(s); // (s)->sxpinfo.trace フラグが立っていればレポートを出力 if (RTRACE(s) && !(TYPEOF(s) == CLOSXP || TYPEOF(s) == BUILTINSXP || TYPEOF(s) == SPECIALSXP || TYPEOF(s) == PROMSXP || TYPEOF(s) == ENVSXP)){ memtrace_report(s,t); // コピーしたノードにもフラグを立てる SET_RTRACE(t,1); } return t; }
  • 19. tracemem の挙動 duplicate が呼ばれないコピーはトレースできない > tracemem(a <- 1:5) [1] "<0x103011a48>" > b <- a > b[1] <- 1 # そのまま代入した場合はトレースされる tracemem[0x103011a48 -> 0x101b41760]: tracemem[0x101b41760 -> 0x103063188]: > c <- a[1:5] > c[1] <- 1 # インデックスを指定した場合はトレースされない > tracemem(a <- list(a = 1:5)) [1] "<0x1064c0958>" > b <- a > a$a <- 1 # そのまま代入した場合はトレースされる tracemem[0x1064c0958 -> 0x1067e9598]: > c <- a$a > c[1] <- 1 # 一部の要素の代入はトレースされない
  • 20.
  • 21. 参考文献 • R Internals - 1.1 SEXPs http://cran.r-project.org/doc/manuals/R-ints.html#SEXPs • RObjectModel - r-optimization-engine - Optimizing the performance of R - Google Project Hosting http://code.google.com/p/r-optimization-engine/wiki/ RObjectModel • R 2.15.2 のソースコード 主に src/include/Rinternals.h, src/main/include/Defn.h, src/main/memory.c
  • 22. 変更履歴 • 2012/12/15 世代別 GC の旧世代の世代数が2なのに3になっていたのを訂正