SlideShare a Scribd company logo
1 of 19
Download to read offline
8.4.3 Real-Time Deques

      2012-08-04 (初版)
      2012-08-14 (2版)
         @yuga
目次
•   狙い
•   実装
•   解析
•   Exercise 8.7
•   おまけ
狙い
• すべての操作が最悪実行時間O(1)であるDequeを作ります。
• 8.4.2で登場したBankersDequeを拡張して実現します。
実装
• BankersDqeueはAmortized Boundなデータ構造であるので、
  7章で学習した手順でWorst-Case Boundなデータ構造へと変
  換していきます。

  1.   Monolithic関数をIncremental関数に変換します
  2.   Dequeの各操作ごとにサスペンションを少しずつ実行するスケジュー
       ルを導入します
BankersDequeで使用したmonolithic関数
BankersDqueでは、フロントとリアの2つのStreamを、以下のように操作してローテーション
を行っていました。

         1.      長い方のStreamを全体の半分の長さだけ残す
                     – 残す方をtakeで取得
                     – 半分を超える部分をdropで作成

         2.      半分を超える部分をreverseして短い方のstreamと結合
                 (これで2つのstreamが同じ長さになる)
                 –    半分を超える部分をreverse
                 –    短い方のリストを前にしてreverseした結果と++

         Queueの場合はリアを空にしてフロントにすべて寄せていましたが、Dequeではフロントとリアの長さを同じ
         にします。

|f| < |r| の場合:

    val r’ = take (j, r)
    val f’ = f ++ reverse (drop (j, r))

ここに登場したtake/drop/reverseの各関数は、4章で定義されたものです。
Streamの実装(参考)
P36 の Figure 4.1 より                     サスペンションを1つ潰すが、
                                        新しいStreamのために構築したサスペンショ
                                        ンで、後続の処理を遅延させる
  fun lazy   ($NIL) ++ t = t
         |   ($CONS (x, s)) ++ t = $CONS (x, s ++ t)           incremental関数
  fun lazy   take (0, s) = $NIL
         |   take (n, $NIL) = $NIL
         |   take (n, $CONS (x, s)) = $CONS (x, take (n-1, s))

  fun lazy drop (n, s) =
        let fun drop’ (0, s) = s
              | drop’ (n, $NIL) = $NIL
              | drop’ (n, $CONS (x, s)) = drop’ (n-1, s)
        in drop’ (n, s) end
  fun lazy reverse s =                                       monolithic関数
        let fun reverse’ ($NIL, r) = r
              | reverse’ ($CONS (x, s), r) = reverse’ (s, $CONS (x, r))
        in reverse’ (s, $NIL) end

                                      既存のサスペンションをすべて潰しながら、
                                      新たなStreamを終端から構築する
monolithic関数からincremental関数へ

BankersDequeでのStream操作を分類します。
  – Incremental関数
     • take
     • ++
  – monolithic関数
     • reverse
     • drop


以上から、RealTimeDeque専用のdropとreverseを用意します。
  – rotateDrop
  – rotateRev
rotateDrop / rotateRevの戦略
•   Incremenetal関数への変換
    – Streamに対する処理を分割して実行し、毎回一定数(𝑐 > 1)ずつ処理を行う
      ようにします。

      ⇒ 一定数ずつ処理することで、1回の処理時間がO(1)になる。


•   スケジュールの導入
    – ローテーションの結果として新規作成されるStreamのデータ構築子$CONSを
      サスペンションとして、その内側に関数の呼び出しを配置して実行を遅延しま
      す。
    – Sectio7.2のRealTimeQueueと同様に、 Streamを先頭から順に開いていくこと
      でサスペンションを潰していく、スケジュール機構を構築します。
rotateDrop
1実行ごとに c ずつdropします。rotateDropの各回の呼び出しは、短い方の
Streamを再作成する$CONSの内側に配置します。

    fun rotateDrop (f, j, r)=
          if j < c then rotateRev (f, drop (j, r), $NIL)             ①
          else let val ($CONS (x, f’)) = f
               in $CONS (x, rotateDrop (f’, j – c, drop (c, r))) end ②




                                       ②

                                       ①            c=3 の場合
rotateRev
1実行ごとに c ずつreverseします。rotateDropの各回の呼び出しは、短い方
のStreamを再作成する$CONSの内側に配置します。

    fun rotateRev ($NIL, r, a) = reverse r ++ a
      | rotateRev ($CONS (x, f), r, a) =
          $CONS (x, rotateRev (f, drop (c, r), reverse (take (c, r)) ++ a))




                                                        c=3 の場合
ローテーション後のフロントとリア
新たに作成されたStreamに内包されて処理が遅延しています。
サスペンションはフロントとリアの両方に作成されます。

                      フロント                    リア

               rotateRev が作成

   rotateDrop が作成               ++ が作成     take が作成




          drop         drop        ++         take
       rotateDrop      take
                     reverse                           Streamの$CONSで
                        ++
                                                       遅延している処理
                    rotateRev

                                ++ や take 自身が再帰して作成す
                                るので、他の処理を内包できない
                                (専用のを作れば別だろうけど)
スケジュールの導入
ローテーション実行中にrotateDrop関数と rotateRev関数が作成したサスペンションを、
次回のローテーション開始までに全て実行しなければなりません。

このためにスケジュールを導入します。
  type ‘a queue = int * ‘a Stream * ‘a Stream   (* front *)
                * int * ‘a Stream * ‘a Stream   (* rear *)

          データサイズ           データ           スケジュール

ローテーションで新しいフロントとリアができるので、そのままスケジュールとします。
  let j = (lenf + lenr) / 2; let i = lenf + lenr –j;
  let r' = S.take (j, r); let f' = rotateDrop (f, j, r)
  in (i, f', f', j, r', r')


Streamを順に開いていくことでサスペンションを実行します。
  fun exec1 ($CONS (x, s)) = s
    | exec1 s = s
解析
短い方のStreamもとに作成する$CONSで rotateDrop と rotateRev を遅延させ
ることができるように、Balance Invariantを設定します。

•   Balance Invariant:
           𝑓 ≤ 𝑐× 𝑟 +1        𝑟 ≤ 𝑐 × 𝑓 + 1 (BankersDequeと同じ)


•   上記から、ローテーション開始時のフロントとリアの長さ:
                  短い方 = 𝑚
                  長い方 = 𝑐 × 𝑚 + 𝑘 + 1       𝑤ℎ𝑒𝑟𝑒 1 ≤ 𝑘 ≤ 𝑐

    例)
     c=3の場合、以下のような状態と操作でローテーションが開始する
        k=1: |f|=5, |r|=16 のときの snoc、|f|=6, |r|=17 のときの tail
        k=2: |f|=6, |r|=18 のときの tail
        k=3: |f|=6, |r|=19 のときの tail
解析
定数 c の範囲を求めます。

•   定数 c の範囲
    – 定数 j を長い方から短い方へ移動する長さとする。

    – rotateRev 開始時に以下が成立する。
         長い方 ≥ 𝑐 × 短い方 + 1 + 𝑘 − 𝑗 𝑚𝑜𝑑 𝑐

    –   長い方 ≥ 𝑐 × 短い方 , 1 ≤ 𝑘 ≤ 𝑐, 𝑐 > 1 なので、
         1 + 𝑘 − 𝑗 𝑚𝑜𝑑 𝑐 ≥ 0
         1 + 1 − 𝑐 − 1 ≥ 0 (k の最小値と j mod c の最大値を代入)
         𝑐≤3

    –   𝑐 = 2 または 𝑐 = 3
解析
•   ローテーション後のフロントとリアの長さ:
                                           𝑓 + |𝑟|
               ローテーション前に短かった方 =
                                             2
                                           𝑓 + |𝑟|
               ローテーション前に長かった方 =
                                             2

•   次回ローテション実行までの最短操作回数
                                           1
    – Init / tail のどちらかを連続実行します(cons / snoc よりも 倍の回数ですむ)。
                                           𝑐
    – ローテーション後のフロント、リアの長さをともに n とすると

                 𝑐 × 𝑛 − 最短操作回数 + 2 ≤ 𝑛
                               𝑛−2
                 𝑛 − 最短操作回数 ≤
                                𝑐
                               𝑛−2   𝑛+2   𝑛
                 最短操作回数 ≥ 𝑛 −      =     >
                                𝑐      𝑐   𝑐
      𝑛+2                                        𝑛
         の項が最大になるのは𝑐 = 2のときで、init / tail を最短で約 回実行すると、次のロー
       𝑐                                      2
      テーションが発生します。
Exercise 8.7
•   ローテーションで作成されるサスペンション数は、フロントとリアともにStream
    の長さと一致します。

•   Debits Invariantを以下のように設定します。
    – ローテーション開始時の 𝑐 × 短い方 + 1 + 𝑘 ≥ 長い方 𝑤ℎ𝑒𝑟𝑒 1 ≤ 𝑘 ≤ 𝑐 から、
       一方の𝑆𝑡𝑟𝑒𝑎𝑚の未評価サスペンション数 ≤ 𝑐 × 短い方 + 2 − 長い方

      さらに次回ローテション実行までの最短操作回数の考察から c = 2 を代入して、
      一方のStreamの未評価サスペンション数 ≤ 2 × 短い方 + 2 − 長い方


•   以上から
    – ローテーション実行直後、短い方と長い方の長さは高々1違うだけなので、Debits Invariantを
      満たしている。
    – Dequeから削除するとき、短い方が1短くなっても、2つのStreamのいずれも、サスペンション
      を2減らせばDebits Invariantを維持できる。
    – Dequeに追加するとき、長い方が1短くなっても、2つのStreamのいずれも、サスペンションを1
      減らせばDebits Invariantを維持できる。
おまけ: RealTimeDequeの動作例
例) Dequeの操作とローテーション

   1. c = 3, |f| = 3, |r| = 9 の RealTimeDeque q1 に対して
       •   snoc q1 x
           ⇒ |f| = 3, |r| = 10
       •   snoc (snoc q1 x) y
           ⇒ |f| = 3, |r| = 11
           ⇒ ローテーション
           ⇒ |f| = 7, |r| = 7

   2. c=3, |f| = 7, |r| = 18 の RealTimeDeque q2 に対して
       •   tail q2
           ⇒ |f| = 6, |r| = 18
       •   tail (tail q2)
           ⇒ |f| = 5, |r| = 18
           ⇒ ローテーション
           ⇒ |f| = 12, |r| = 11


OCamlによるサンプルコード:
   https://gist.github.com/3271021
おまけ: Global Rebuildingとの違い
だいたいこんな感じだと思います。

•   Global Rebuildingには必要だったローテーション用のコピーが、Lazy Rebuildingで
    は不要。
•   Global Rebuildingを使用したHood MelvilleQueueでは、ローテーションに必要な処
    理が比較的均等に分散していたが、Lazy Rebuildingを使用したRealTimeDequeで
    は、短い方のStreamを再作成する$CONSだけを使ってdropやreverse遅延させて
    いるので、サスペンションの実行コストに偏りがある。
参考文献
•   Chris Okasaki, “8.4.3 Real-Time Deque”, Purely Functional Data Structures,
    Cambridge University Press (1999)
•   Chris Okasaki, “Simple and efficient purely functional queues and deques”, Journal
    of Functional Programming, 5(4):583-592, October 1995

More Related Content

What's hot

V6でJIT・部分適用・継続
V6でJIT・部分適用・継続V6でJIT・部分適用・継続
V6でJIT・部分適用・継続7shi
 
Snake eats leapfrog (in Japanese)
Snake eats leapfrog (in Japanese)Snake eats leapfrog (in Japanese)
Snake eats leapfrog (in Japanese)Keigo Nitadori
 
Rubyの御先祖CLU(くるう)のお話(OSC2013 Hamamatsu 発表資料)
Rubyの御先祖CLU(くるう)のお話(OSC2013 Hamamatsu 発表資料)Rubyの御先祖CLU(くるう)のお話(OSC2013 Hamamatsu 発表資料)
Rubyの御先祖CLU(くるう)のお話(OSC2013 Hamamatsu 発表資料)洋史 東平
 
Java8 lambdas chap03
Java8 lambdas chap03Java8 lambdas chap03
Java8 lambdas chap03ohtsuchi
 
Common LispでGPGPU
Common LispでGPGPUCommon LispでGPGPU
Common LispでGPGPUgos-k
 
Erlang で再帰
Erlang で再帰Erlang で再帰
Erlang で再帰snow long
 
OpenFOAMの壁関数
OpenFOAMの壁関数OpenFOAMの壁関数
OpenFOAMの壁関数Fumiya Nozaki
 
難しそうで難しくない少し難しいClojure並行処理
難しそうで難しくない少し難しいClojure並行処理難しそうで難しくない少し難しいClojure並行処理
難しそうで難しくない少し難しいClojure並行処理Naoyuki Kakuda
 
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたMITSUNARI Shigeo
 
Turbulence Models in OpenFOAM
Turbulence Models in OpenFOAMTurbulence Models in OpenFOAM
Turbulence Models in OpenFOAMFumiya Nozaki
 
Learning Depthwise Separable Graph Convolution from Data Manifold
Learning Depthwise Separable Graph Convolution from Data ManifoldLearning Depthwise Separable Graph Convolution from Data Manifold
Learning Depthwise Separable Graph Convolution from Data Manifoldyukihiro domae
 
現実世界のJRuby(ショートバージョン)
現実世界のJRuby(ショートバージョン)現実世界のJRuby(ショートバージョン)
現実世界のJRuby(ショートバージョン)Hiroshi Nakamura
 
FeaStNet: Feature-Steered Graph Convolutions for 3D Shape Analysis
FeaStNet: Feature-Steered Graph Convolutions for 3D Shape AnalysisFeaStNet: Feature-Steered Graph Convolutions for 3D Shape Analysis
FeaStNet: Feature-Steered Graph Convolutions for 3D Shape Analysisyukihiro domae
 
OpenFOAM -空間の離散化と係数行列の取り扱い(Spatial Discretization and Coefficient Matrix)-
OpenFOAM -空間の離散化と係数行列の取り扱い(Spatial Discretization and Coefficient Matrix)-OpenFOAM -空間の離散化と係数行列の取り扱い(Spatial Discretization and Coefficient Matrix)-
OpenFOAM -空間の離散化と係数行列の取り扱い(Spatial Discretization and Coefficient Matrix)-Fumiya Nozaki
 
Rubyの御先祖CLUのお話(原本)
Rubyの御先祖CLUのお話(原本)Rubyの御先祖CLUのお話(原本)
Rubyの御先祖CLUのお話(原本)洋史 東平
 

What's hot (20)

V6でJIT・部分適用・継続
V6でJIT・部分適用・継続V6でJIT・部分適用・継続
V6でJIT・部分適用・継続
 
Snake eats leapfrog (in Japanese)
Snake eats leapfrog (in Japanese)Snake eats leapfrog (in Japanese)
Snake eats leapfrog (in Japanese)
 
Rubyの御先祖CLU(くるう)のお話(OSC2013 Hamamatsu 発表資料)
Rubyの御先祖CLU(くるう)のお話(OSC2013 Hamamatsu 発表資料)Rubyの御先祖CLU(くるう)のお話(OSC2013 Hamamatsu 発表資料)
Rubyの御先祖CLU(くるう)のお話(OSC2013 Hamamatsu 発表資料)
 
HPC Phys-20201203
HPC Phys-20201203HPC Phys-20201203
HPC Phys-20201203
 
Test
TestTest
Test
 
Java8 lambdas chap03
Java8 lambdas chap03Java8 lambdas chap03
Java8 lambdas chap03
 
ADVENTURE_Thermalの概要
ADVENTURE_Thermalの概要ADVENTURE_Thermalの概要
ADVENTURE_Thermalの概要
 
Common LispでGPGPU
Common LispでGPGPUCommon LispでGPGPU
Common LispでGPGPU
 
Erlang で再帰
Erlang で再帰Erlang で再帰
Erlang で再帰
 
OpenFOAMの壁関数
OpenFOAMの壁関数OpenFOAMの壁関数
OpenFOAMの壁関数
 
難しそうで難しくない少し難しいClojure並行処理
難しそうで難しくない少し難しいClojure並行処理難しそうで難しくない少し難しいClojure並行処理
難しそうで難しくない少し難しいClojure並行処理
 
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみた
 
Turbulence Models in OpenFOAM
Turbulence Models in OpenFOAMTurbulence Models in OpenFOAM
Turbulence Models in OpenFOAM
 
Learning Depthwise Separable Graph Convolution from Data Manifold
Learning Depthwise Separable Graph Convolution from Data ManifoldLearning Depthwise Separable Graph Convolution from Data Manifold
Learning Depthwise Separable Graph Convolution from Data Manifold
 
Meeting10
Meeting10Meeting10
Meeting10
 
現実世界のJRuby(ショートバージョン)
現実世界のJRuby(ショートバージョン)現実世界のJRuby(ショートバージョン)
現実世界のJRuby(ショートバージョン)
 
FeaStNet: Feature-Steered Graph Convolutions for 3D Shape Analysis
FeaStNet: Feature-Steered Graph Convolutions for 3D Shape AnalysisFeaStNet: Feature-Steered Graph Convolutions for 3D Shape Analysis
FeaStNet: Feature-Steered Graph Convolutions for 3D Shape Analysis
 
前期講座09
前期講座09前期講座09
前期講座09
 
OpenFOAM -空間の離散化と係数行列の取り扱い(Spatial Discretization and Coefficient Matrix)-
OpenFOAM -空間の離散化と係数行列の取り扱い(Spatial Discretization and Coefficient Matrix)-OpenFOAM -空間の離散化と係数行列の取り扱い(Spatial Discretization and Coefficient Matrix)-
OpenFOAM -空間の離散化と係数行列の取り扱い(Spatial Discretization and Coefficient Matrix)-
 
Rubyの御先祖CLUのお話(原本)
Rubyの御先祖CLUのお話(原本)Rubyの御先祖CLUのお話(原本)
Rubyの御先祖CLUのお話(原本)
 

Viewers also liked

Jorge oteiza
Jorge oteizaJorge oteiza
Jorge oteizaadriana96
 
Jorge Oteiza
Jorge OteizaJorge Oteiza
Jorge Oteizahirune
 
Oteiza
OteizaOteiza
Oteizajessi
 
Una interpretación. jorge oteiza
Una interpretación.     jorge oteizaUna interpretación.     jorge oteiza
Una interpretación. jorge oteizaIsrael Alvarado
 
Jorge Oteiza
Jorge OteizaJorge Oteiza
Jorge Oteizahirune
 
Caja metafisica
Caja metafisicaCaja metafisica
Caja metafisicamek97
 
IV Encuentros de Centros de Documentación de Arte Contemporáneo ARTIUM - Borj...
IV Encuentros de Centros de Documentación de Arte Contemporáneo ARTIUM - Borj...IV Encuentros de Centros de Documentación de Arte Contemporáneo ARTIUM - Borj...
IV Encuentros de Centros de Documentación de Arte Contemporáneo ARTIUM - Borj...Artium Vitoria
 

Viewers also liked (10)

Jorge oteiza
Jorge oteizaJorge oteiza
Jorge oteiza
 
Jorge oteiza
Jorge oteizaJorge oteiza
Jorge oteiza
 
Jorge Oteiza
Jorge OteizaJorge Oteiza
Jorge Oteiza
 
Oteiza
OteizaOteiza
Oteiza
 
Una interpretación. jorge oteiza
Una interpretación.     jorge oteizaUna interpretación.     jorge oteiza
Una interpretación. jorge oteiza
 
Jorge Oteiza
Jorge OteizaJorge Oteiza
Jorge Oteiza
 
Caja metafisica
Caja metafisicaCaja metafisica
Caja metafisica
 
Oteiza Acercamiento I
Oteiza Acercamiento IOteiza Acercamiento I
Oteiza Acercamiento I
 
Filosofia Oteiza
Filosofia OteizaFilosofia Oteiza
Filosofia Oteiza
 
IV Encuentros de Centros de Documentación de Arte Contemporáneo ARTIUM - Borj...
IV Encuentros de Centros de Documentación de Arte Contemporáneo ARTIUM - Borj...IV Encuentros de Centros de Documentación de Arte Contemporáneo ARTIUM - Borj...
IV Encuentros de Centros de Documentación de Arte Contemporáneo ARTIUM - Borj...
 

Similar to PFDS 8.4.3 Real-Time Deques

x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチMasami Ichikawa
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.ContextAkira Takahashi
 
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!bitter_fox
 
Read daemon on 20121110 by shinaisan
Read daemon on 20121110 by shinaisanRead daemon on 20121110 by shinaisan
Read daemon on 20121110 by shinaisanshinaisan
 
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目hecomi
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門Hideyuki Tanaka
 
OpenFlowで覚えるネットワーク
OpenFlowで覚えるネットワークOpenFlowで覚えるネットワーク
OpenFlowで覚えるネットワークM Hagiwara
 
モナドをつくろう
モナドをつくろうモナドをつくろう
モナドをつくろうdico_leque
 
PostgreSQL実行計画入門@関西PostgreSQL勉強会
PostgreSQL実行計画入門@関西PostgreSQL勉強会PostgreSQL実行計画入門@関西PostgreSQL勉強会
PostgreSQL実行計画入門@関西PostgreSQL勉強会Satoshi Yamada
 
Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用Seiya Tokui
 
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部NVIDIA Japan
 
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)Satoshi Yamada
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミングOuka Yuka
 
20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸Takahiro Iwase
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装MITSUNARI Shigeo
 

Similar to PFDS 8.4.3 Real-Time Deques (20)

x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチ
 
Convex Hull Trick
Convex Hull TrickConvex Hull Trick
Convex Hull Trick
 
Rの高速化
Rの高速化Rの高速化
Rの高速化
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
 
10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!10のJava9で変わるJava8の嫌なとこ!
10のJava9で変わるJava8の嫌なとこ!
 
Read daemon on 20121110 by shinaisan
Read daemon on 20121110 by shinaisanRead daemon on 20121110 by shinaisan
Read daemon on 20121110 by shinaisan
 
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
OpenFlowで覚えるネットワーク
OpenFlowで覚えるネットワークOpenFlowで覚えるネットワーク
OpenFlowで覚えるネットワーク
 
モナドをつくろう
モナドをつくろうモナドをつくろう
モナドをつくろう
 
osoljp 2011.08
osoljp 2011.08osoljp 2011.08
osoljp 2011.08
 
PostgreSQL実行計画入門@関西PostgreSQL勉強会
PostgreSQL実行計画入門@関西PostgreSQL勉強会PostgreSQL実行計画入門@関西PostgreSQL勉強会
PostgreSQL実行計画入門@関西PostgreSQL勉強会
 
Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用
 
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部
 
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
 
optimal Ate pairing
optimal Ate pairingoptimal Ate pairing
optimal Ate pairing
 
20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸20120317 IT系勉強会 in 神戸
20120317 IT系勉強会 in 神戸
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装
 
Tokyor23 doradora09
Tokyor23 doradora09Tokyor23 doradora09
Tokyor23 doradora09
 

More from 昌平 村山

PFDS 11.2 catenable double ended queue
PFDS 11.2 catenable double ended queuePFDS 11.2 catenable double ended queue
PFDS 11.2 catenable double ended queue昌平 村山
 
PFDS 10.2.2 heaps with efficient merging
PFDS 10.2.2 heaps with efficient mergingPFDS 10.2.2 heaps with efficient merging
PFDS 10.2.2 heaps with efficient merging昌平 村山
 
PFDS 10.2.1 lists with efficient catenation
PFDS 10.2.1 lists with efficient catenationPFDS 10.2.1 lists with efficient catenation
PFDS 10.2.1 lists with efficient catenation昌平 村山
 
PFDS 9.2.3 Lazy Representations
PFDS 9.2.3 Lazy RepresentationsPFDS 9.2.3 Lazy Representations
PFDS 9.2.3 Lazy Representations昌平 村山
 
PFDS 5.5 Pairing heap
PFDS 5.5 Pairing heapPFDS 5.5 Pairing heap
PFDS 5.5 Pairing heap昌平 村山
 

More from 昌平 村山 (6)

PFDS 11.2 catenable double ended queue
PFDS 11.2 catenable double ended queuePFDS 11.2 catenable double ended queue
PFDS 11.2 catenable double ended queue
 
PFDS 10.2.2 heaps with efficient merging
PFDS 10.2.2 heaps with efficient mergingPFDS 10.2.2 heaps with efficient merging
PFDS 10.2.2 heaps with efficient merging
 
PFDS 10.2.1 lists with efficient catenation
PFDS 10.2.1 lists with efficient catenationPFDS 10.2.1 lists with efficient catenation
PFDS 10.2.1 lists with efficient catenation
 
PFDS 9.2.3 Lazy Representations
PFDS 9.2.3 Lazy RepresentationsPFDS 9.2.3 Lazy Representations
PFDS 9.2.3 Lazy Representations
 
PFDS chart
PFDS chartPFDS chart
PFDS chart
 
PFDS 5.5 Pairing heap
PFDS 5.5 Pairing heapPFDS 5.5 Pairing heap
PFDS 5.5 Pairing heap
 

Recently uploaded

論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 

Recently uploaded (8)

論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 

PFDS 8.4.3 Real-Time Deques

  • 1. 8.4.3 Real-Time Deques 2012-08-04 (初版) 2012-08-14 (2版) @yuga
  • 2. 目次 • 狙い • 実装 • 解析 • Exercise 8.7 • おまけ
  • 4. 実装 • BankersDqeueはAmortized Boundなデータ構造であるので、 7章で学習した手順でWorst-Case Boundなデータ構造へと変 換していきます。 1. Monolithic関数をIncremental関数に変換します 2. Dequeの各操作ごとにサスペンションを少しずつ実行するスケジュー ルを導入します
  • 5. BankersDequeで使用したmonolithic関数 BankersDqueでは、フロントとリアの2つのStreamを、以下のように操作してローテーション を行っていました。 1. 長い方のStreamを全体の半分の長さだけ残す – 残す方をtakeで取得 – 半分を超える部分をdropで作成 2. 半分を超える部分をreverseして短い方のstreamと結合 (これで2つのstreamが同じ長さになる) – 半分を超える部分をreverse – 短い方のリストを前にしてreverseした結果と++ Queueの場合はリアを空にしてフロントにすべて寄せていましたが、Dequeではフロントとリアの長さを同じ にします。 |f| < |r| の場合: val r’ = take (j, r) val f’ = f ++ reverse (drop (j, r)) ここに登場したtake/drop/reverseの各関数は、4章で定義されたものです。
  • 6. Streamの実装(参考) P36 の Figure 4.1 より サスペンションを1つ潰すが、 新しいStreamのために構築したサスペンショ ンで、後続の処理を遅延させる fun lazy ($NIL) ++ t = t | ($CONS (x, s)) ++ t = $CONS (x, s ++ t) incremental関数 fun lazy take (0, s) = $NIL | take (n, $NIL) = $NIL | take (n, $CONS (x, s)) = $CONS (x, take (n-1, s)) fun lazy drop (n, s) = let fun drop’ (0, s) = s | drop’ (n, $NIL) = $NIL | drop’ (n, $CONS (x, s)) = drop’ (n-1, s) in drop’ (n, s) end fun lazy reverse s = monolithic関数 let fun reverse’ ($NIL, r) = r | reverse’ ($CONS (x, s), r) = reverse’ (s, $CONS (x, r)) in reverse’ (s, $NIL) end 既存のサスペンションをすべて潰しながら、 新たなStreamを終端から構築する
  • 7. monolithic関数からincremental関数へ BankersDequeでのStream操作を分類します。 – Incremental関数 • take • ++ – monolithic関数 • reverse • drop 以上から、RealTimeDeque専用のdropとreverseを用意します。 – rotateDrop – rotateRev
  • 8. rotateDrop / rotateRevの戦略 • Incremenetal関数への変換 – Streamに対する処理を分割して実行し、毎回一定数(𝑐 > 1)ずつ処理を行う ようにします。 ⇒ 一定数ずつ処理することで、1回の処理時間がO(1)になる。 • スケジュールの導入 – ローテーションの結果として新規作成されるStreamのデータ構築子$CONSを サスペンションとして、その内側に関数の呼び出しを配置して実行を遅延しま す。 – Sectio7.2のRealTimeQueueと同様に、 Streamを先頭から順に開いていくこと でサスペンションを潰していく、スケジュール機構を構築します。
  • 9. rotateDrop 1実行ごとに c ずつdropします。rotateDropの各回の呼び出しは、短い方の Streamを再作成する$CONSの内側に配置します。 fun rotateDrop (f, j, r)= if j < c then rotateRev (f, drop (j, r), $NIL) ① else let val ($CONS (x, f’)) = f in $CONS (x, rotateDrop (f’, j – c, drop (c, r))) end ② ② ① c=3 の場合
  • 10. rotateRev 1実行ごとに c ずつreverseします。rotateDropの各回の呼び出しは、短い方 のStreamを再作成する$CONSの内側に配置します。 fun rotateRev ($NIL, r, a) = reverse r ++ a | rotateRev ($CONS (x, f), r, a) = $CONS (x, rotateRev (f, drop (c, r), reverse (take (c, r)) ++ a)) c=3 の場合
  • 11. ローテーション後のフロントとリア 新たに作成されたStreamに内包されて処理が遅延しています。 サスペンションはフロントとリアの両方に作成されます。 フロント リア rotateRev が作成 rotateDrop が作成 ++ が作成 take が作成 drop drop ++ take rotateDrop take reverse Streamの$CONSで ++ 遅延している処理 rotateRev ++ や take 自身が再帰して作成す るので、他の処理を内包できない (専用のを作れば別だろうけど)
  • 12. スケジュールの導入 ローテーション実行中にrotateDrop関数と rotateRev関数が作成したサスペンションを、 次回のローテーション開始までに全て実行しなければなりません。 このためにスケジュールを導入します。 type ‘a queue = int * ‘a Stream * ‘a Stream (* front *) * int * ‘a Stream * ‘a Stream (* rear *) データサイズ データ スケジュール ローテーションで新しいフロントとリアができるので、そのままスケジュールとします。 let j = (lenf + lenr) / 2; let i = lenf + lenr –j; let r' = S.take (j, r); let f' = rotateDrop (f, j, r) in (i, f', f', j, r', r') Streamを順に開いていくことでサスペンションを実行します。 fun exec1 ($CONS (x, s)) = s | exec1 s = s
  • 13. 解析 短い方のStreamもとに作成する$CONSで rotateDrop と rotateRev を遅延させ ることができるように、Balance Invariantを設定します。 • Balance Invariant: 𝑓 ≤ 𝑐× 𝑟 +1 𝑟 ≤ 𝑐 × 𝑓 + 1 (BankersDequeと同じ) • 上記から、ローテーション開始時のフロントとリアの長さ: 短い方 = 𝑚 長い方 = 𝑐 × 𝑚 + 𝑘 + 1 𝑤ℎ𝑒𝑟𝑒 1 ≤ 𝑘 ≤ 𝑐 例) c=3の場合、以下のような状態と操作でローテーションが開始する k=1: |f|=5, |r|=16 のときの snoc、|f|=6, |r|=17 のときの tail k=2: |f|=6, |r|=18 のときの tail k=3: |f|=6, |r|=19 のときの tail
  • 14. 解析 定数 c の範囲を求めます。 • 定数 c の範囲 – 定数 j を長い方から短い方へ移動する長さとする。 – rotateRev 開始時に以下が成立する。 長い方 ≥ 𝑐 × 短い方 + 1 + 𝑘 − 𝑗 𝑚𝑜𝑑 𝑐 – 長い方 ≥ 𝑐 × 短い方 , 1 ≤ 𝑘 ≤ 𝑐, 𝑐 > 1 なので、 1 + 𝑘 − 𝑗 𝑚𝑜𝑑 𝑐 ≥ 0 1 + 1 − 𝑐 − 1 ≥ 0 (k の最小値と j mod c の最大値を代入) 𝑐≤3 – 𝑐 = 2 または 𝑐 = 3
  • 15. 解析 • ローテーション後のフロントとリアの長さ: 𝑓 + |𝑟| ローテーション前に短かった方 = 2 𝑓 + |𝑟| ローテーション前に長かった方 = 2 • 次回ローテション実行までの最短操作回数 1 – Init / tail のどちらかを連続実行します(cons / snoc よりも 倍の回数ですむ)。 𝑐 – ローテーション後のフロント、リアの長さをともに n とすると 𝑐 × 𝑛 − 最短操作回数 + 2 ≤ 𝑛 𝑛−2 𝑛 − 最短操作回数 ≤ 𝑐 𝑛−2 𝑛+2 𝑛 最短操作回数 ≥ 𝑛 − = > 𝑐 𝑐 𝑐 𝑛+2 𝑛 の項が最大になるのは𝑐 = 2のときで、init / tail を最短で約 回実行すると、次のロー 𝑐 2 テーションが発生します。
  • 16. Exercise 8.7 • ローテーションで作成されるサスペンション数は、フロントとリアともにStream の長さと一致します。 • Debits Invariantを以下のように設定します。 – ローテーション開始時の 𝑐 × 短い方 + 1 + 𝑘 ≥ 長い方 𝑤ℎ𝑒𝑟𝑒 1 ≤ 𝑘 ≤ 𝑐 から、 一方の𝑆𝑡𝑟𝑒𝑎𝑚の未評価サスペンション数 ≤ 𝑐 × 短い方 + 2 − 長い方 さらに次回ローテション実行までの最短操作回数の考察から c = 2 を代入して、 一方のStreamの未評価サスペンション数 ≤ 2 × 短い方 + 2 − 長い方 • 以上から – ローテーション実行直後、短い方と長い方の長さは高々1違うだけなので、Debits Invariantを 満たしている。 – Dequeから削除するとき、短い方が1短くなっても、2つのStreamのいずれも、サスペンション を2減らせばDebits Invariantを維持できる。 – Dequeに追加するとき、長い方が1短くなっても、2つのStreamのいずれも、サスペンションを1 減らせばDebits Invariantを維持できる。
  • 17. おまけ: RealTimeDequeの動作例 例) Dequeの操作とローテーション 1. c = 3, |f| = 3, |r| = 9 の RealTimeDeque q1 に対して • snoc q1 x ⇒ |f| = 3, |r| = 10 • snoc (snoc q1 x) y ⇒ |f| = 3, |r| = 11 ⇒ ローテーション ⇒ |f| = 7, |r| = 7 2. c=3, |f| = 7, |r| = 18 の RealTimeDeque q2 に対して • tail q2 ⇒ |f| = 6, |r| = 18 • tail (tail q2) ⇒ |f| = 5, |r| = 18 ⇒ ローテーション ⇒ |f| = 12, |r| = 11 OCamlによるサンプルコード: https://gist.github.com/3271021
  • 18. おまけ: Global Rebuildingとの違い だいたいこんな感じだと思います。 • Global Rebuildingには必要だったローテーション用のコピーが、Lazy Rebuildingで は不要。 • Global Rebuildingを使用したHood MelvilleQueueでは、ローテーションに必要な処 理が比較的均等に分散していたが、Lazy Rebuildingを使用したRealTimeDequeで は、短い方のStreamを再作成する$CONSだけを使ってdropやreverse遅延させて いるので、サスペンションの実行コストに偏りがある。
  • 19. 参考文献 • Chris Okasaki, “8.4.3 Real-Time Deque”, Purely Functional Data Structures, Cambridge University Press (1999) • Chris Okasaki, “Simple and efficient purely functional queues and deques”, Journal of Functional Programming, 5(4):583-592, October 1995