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

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になっていたのを訂正
1 of 22

Recommended

Rの高速化 by
Rの高速化Rの高速化
Rの高速化弘毅 露崎
39.3K views33 slides
Rにおける大規模データ解析(第10回TokyoWebMining) by
Rにおける大規模データ解析(第10回TokyoWebMining)Rにおける大規模データ解析(第10回TokyoWebMining)
Rにおける大規模データ解析(第10回TokyoWebMining)Shintaro Fukushima
44.7K views70 slides
巨大な表を高速に扱うData.table について by
巨大な表を高速に扱うData.table について巨大な表を高速に扱うData.table について
巨大な表を高速に扱うData.table についてHaruka Ozaki
8.4K views27 slides
RのffでGLMしてみたけど... by
RのffでGLMしてみたけど...RのffでGLMしてみたけど...
RのffでGLMしてみたけど...Kazuya Wada
11.2K views30 slides
RのffとbigmemoryとRevoScaleRとを比較してみた by
RのffとbigmemoryとRevoScaleRとを比較してみたRのffとbigmemoryとRevoScaleRとを比較してみた
RのffとbigmemoryとRevoScaleRとを比較してみたKazuya Wada
23.1K views24 slides
R-hpc-1 TokyoR#11 by
R-hpc-1 TokyoR#11R-hpc-1 TokyoR#11
R-hpc-1 TokyoR#11Shintaro Fukushima
3.2K views24 slides

More Related Content

What's hot

統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用 by
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用
統計解析言語Rにおける大規模データ管理のためのboost.interprocessの活用Shintaro Fukushima
4.5K views49 slides
Tokyo.R#16 wdkz by
Tokyo.R#16 wdkzTokyo.R#16 wdkz
Tokyo.R#16 wdkzKazuya Wada
7.3K views42 slides
mmapパッケージを使ってお手軽オブジェクト管理 by
mmapパッケージを使ってお手軽オブジェクト管理mmapパッケージを使ってお手軽オブジェクト管理
mmapパッケージを使ってお手軽オブジェクト管理Shintaro Fukushima
1.6K views17 slides
Rあんなときこんなとき(tokyo r#12) by
Rあんなときこんなとき(tokyo r#12)Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Shintaro Fukushima
5.6K views51 slides
Rユーザのためのspark入門 by
Rユーザのためのspark入門Rユーザのためのspark入門
Rユーザのためのspark入門Shintaro Fukushima
10K views39 slides
for関数を使った繰り返し処理によるヒストグラムの一括出力 by
for関数を使った繰り返し処理によるヒストグラムの一括出力for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力imuyaoti
12.5K views35 slides

What's hot(20)

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

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

about dakota6.7 gui by
about dakota6.7 guiabout dakota6.7 gui
about dakota6.7 guiEtsuji Nomura
680 views128 slides
ホームディレクトリに埋もれた便利なコードをさがせ! by
ホームディレクトリに埋もれた便利なコードをさがせ!ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!Yohei Fushii
27.6K views64 slides
tcpdump & xtrabackup @ MySQL Casual Talks #1 by
tcpdump & xtrabackup @ MySQL Casual Talks #1tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1Ryosuke IWANAGA
5.5K views39 slides
これからのコンピューティングとJava(Hacker Tackle) by
これからのコンピューティングとJava(Hacker Tackle)これからのコンピューティングとJava(Hacker Tackle)
これからのコンピューティングとJava(Hacker Tackle)なおき きしだ
4.7K views76 slides
HPC Phys-20201203 by
HPC Phys-20201203HPC Phys-20201203
HPC Phys-20201203MITSUNARI Shigeo
2.8K views27 slides
ラズパイでデバイスドライバを作ってみた。 by
ラズパイでデバイスドライバを作ってみた。ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。Kazuki Onishi
4.5K views44 slides

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

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

More from Takeshi Arabiki

開発の心得 by
開発の心得開発の心得
開発の心得Takeshi Arabiki
5K views18 slides
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜 by
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜Takeshi Arabiki
10.9K views31 slides
Introduction to Japanese Morphological Analysis by
Introduction to Japanese Morphological AnalysisIntroduction to Japanese Morphological Analysis
Introduction to Japanese Morphological AnalysisTakeshi Arabiki
16.8K views25 slides
R による文書分類入門 by
R による文書分類入門R による文書分類入門
R による文書分類入門Takeshi Arabiki
30.7K views59 slides
HTML5 Canvas で学ぶアフィン変換 by
HTML5 Canvas で学ぶアフィン変換HTML5 Canvas で学ぶアフィン変換
HTML5 Canvas で学ぶアフィン変換Takeshi Arabiki
8.9K views29 slides
Introduction to Favmemo for Immature Engineers by
Introduction to Favmemo for Immature EngineersIntroduction to Favmemo for Immature Engineers
Introduction to Favmemo for Immature EngineersTakeshi Arabiki
2.9K views21 slides

More from Takeshi Arabiki(17)

クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜 by Takeshi Arabiki
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜
クックパッド特売情報 における自然言語処理 〜固有表現抽出を利用した検索システム〜
Takeshi Arabiki10.9K views
Introduction to Japanese Morphological Analysis by Takeshi Arabiki
Introduction to Japanese Morphological AnalysisIntroduction to Japanese Morphological Analysis
Introduction to Japanese Morphological Analysis
Takeshi Arabiki16.8K views
R による文書分類入門 by Takeshi Arabiki
R による文書分類入門R による文書分類入門
R による文書分類入門
Takeshi Arabiki30.7K views
HTML5 Canvas で学ぶアフィン変換 by Takeshi Arabiki
HTML5 Canvas で学ぶアフィン変換HTML5 Canvas で学ぶアフィン変換
HTML5 Canvas で学ぶアフィン変換
Takeshi Arabiki8.9K views
Introduction to Favmemo for Immature Engineers by Takeshi Arabiki
Introduction to Favmemo for Immature EngineersIntroduction to Favmemo for Immature Engineers
Introduction to Favmemo for Immature Engineers
Takeshi Arabiki2.9K views
Rのスコープとフレームと環境と by Takeshi Arabiki
Rのスコープとフレームと環境とRのスコープとフレームと環境と
Rのスコープとフレームと環境と
Takeshi Arabiki3.2K views
twitteRで快適Rライフ! by Takeshi Arabiki
twitteRで快適Rライフ!twitteRで快適Rライフ!
twitteRで快適Rライフ!
Takeshi Arabiki8.4K views
RではじめるTwitter解析 by Takeshi Arabiki
RではじめるTwitter解析RではじめるTwitter解析
RではじめるTwitter解析
Takeshi Arabiki23.6K views
Rデータフレーム自由自在 by Takeshi Arabiki
Rデータフレーム自由自在Rデータフレーム自由自在
Rデータフレーム自由自在
Takeshi Arabiki24.3K views
文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜 by Takeshi Arabiki
文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜
文字列カーネルによる辞書なしツイート分類 〜文字列カーネル入門〜
Takeshi Arabiki9.5K views
はじめてのまっぷりでゅ〜す by Takeshi Arabiki
はじめてのまっぷりでゅ〜すはじめてのまっぷりでゅ〜す
はじめてのまっぷりでゅ〜す
Takeshi Arabiki2.3K views
TwitterのデータをRであれこれ by Takeshi Arabiki
TwitterのデータをRであれこれTwitterのデータをRであれこれ
TwitterのデータをRであれこれ
Takeshi Arabiki13.5K views
Twitterのデータを取得する準備 by Takeshi Arabiki
Twitterのデータを取得する準備Twitterのデータを取得する準備
Twitterのデータを取得する準備
Takeshi Arabiki2.8K views

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になっていたのを訂正