Mercurial > hg > Papers > 2016 > kkb-master
comparison slide/index.md @ 20:e077497754a0
revision
author | Shohei KOKUBO <e105744@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 18 Feb 2016 16:13:20 +0900 |
parents | 4dcfec1bf1e7 |
children | f147f579d552 |
comparison
equal
deleted
inserted
replaced
19:4dcfec1bf1e7 | 20:e077497754a0 |
---|---|
59 Gears OS ではプログラムの単位として Gear を用いる。 | 59 Gears OS ではプログラムの単位として Gear を用いる。 |
60 Gear は並列実行の単位、データ分割、Gear 間の接続などになる。 | 60 Gear は並列実行の単位、データ分割、Gear 間の接続などになる。 |
61 | 61 |
62 Code Gear は Code Segment と同等のものである。 | 62 Code Gear は Code Segment と同等のものである。 |
63 Code Gear には任意の数の Data Gear を参照し、処理が完了すると任意の数の Data Gear に書き込みを行う。 | 63 Code Gear には任意の数の Data Gear を参照し、処理が完了すると任意の数の Data Gear に書き込みを行う。 |
64 接続された Data Gear 以外にアクセスすることは | 64 接続された Data Gear 以外にアクセスすることはできない。 |
65 | 65 |
66 Data Gear はデータそのものを表す。 | 66 Data Gear はデータそのものを表す。 |
67 int や文字列などの Primitive Data Type を複数持つ構造体として定義する。 | 67 int や文字列などの Primitive Data Type を複数持つ構造体として定義する。 |
68 | 68 |
69 Gear 特徴として処理やデータの構造が Code/Data Gear に閉じていることにある。 | 69 Gear 特徴として処理やデータの構造が Code/Data Gear に閉じていることにある。 |
104 実行後、必要なデータを Persistent Data Tree に書き出し次の Task を取得する。 | 104 実行後、必要なデータを Persistent Data Tree に書き出し次の Task を取得する。 |
105 | 105 |
106 ![Gears OS の構成](./pictures/gearsos.svg) | 106 ![Gears OS の構成](./pictures/gearsos.svg) |
107 | 107 |
108 # Allocator | 108 # Allocator |
109 | 109 * Context の生成時にある程度の大きさのメモリ領域を確保 |
110 | 110 * Context には確保したメモリ領域を指す情報(heapStart, heap, heapLimit)を格納 |
111 # 測定結果 | 111 |
112 * OS X(10.10.5) | 112 ``` C |
113 * 2.3 GHz Intel Core i7 | 113 /* Context definition example */ |
114 * length:1310720 | 114 #define ALLOCATE_SIZE 1000 |
115 * cpus/(length/task)/time | 115 |
116 * 1/10/0.164748s | 116 // Code Gear Name |
117 * 2/10/0.230114s | 117 enum Code { |
118 * 4/10/0.479126s | 118 Code1, |
119 * 8/10/0.553448s | 119 Code2, |
120 * 1/81920/0.010666s | 120 Allocator, |
121 * 2/81920/0.005303s | 121 Exit, |
122 * 4/81920/0.002657s | 122 }; |
123 * 8/81920/0.002521s | 123 |
124 // Unique Data Gear | |
125 enum UniqueData { | |
126 Allocate, | |
127 }; | |
128 | |
129 struct Context { | |
130 enum Code next; | |
131 int codeNum; | |
132 __code (**code) (struct Context*); | |
133 void* heapStart; | |
134 void* heap; | |
135 long heapLimit; | |
136 int dataNum; | |
137 union Data **data; | |
138 }; | |
139 | |
140 // Data Gear definition | |
141 union Data { | |
142 // size: 4 byte | |
143 struct Data1 { | |
144 int i; | |
145 } data1; | |
146 // size: 5 byte | |
147 struct Data2 { | |
148 int i; | |
149 char c; | |
150 } data2; | |
151 // size: 8 byte | |
152 struct Allocate { | |
153 long size; | |
154 } allocate; | |
155 }; | |
156 ``` | |
157 | |
158 # Allocator | |
159 * Allocation を行うための情報を書き込む Data Gear が必要 | |
160 * Context と同時に生成 | |
161 ``` C | |
162 __code initContext(struct Context* context, int num) { | |
163 context->heapLimit = sizeof(union Data)*ALLOCATE_SIZE; | |
164 context->heapStart = malloc(context->heapLimit); | |
165 context->heap = context->heapStart; | |
166 context->codeNum = Exit; | |
167 | |
168 context->code = malloc(sizeof(__code*)*ALLOCATE_SIZE); | |
169 context->data = malloc(sizeof(union Data*)*ALLOCATE_SIZE); | |
170 | |
171 context->code[Code1] = code1_stub; | |
172 context->code[Code2] = code2_stub; | |
173 context->code[Allocator] = allocator_stub; | |
174 context->code[Exit] = exit_code; | |
175 | |
176 context->data[Allocate] = context->heap; | |
177 context->heap += sizeof(struct Allocate); | |
178 | |
179 context->dataNum = Allocate; | |
180 } | |
181 ``` | |
182 | |
183 # Allocator | |
184 * メモリ領域を指すポインタを動かすことで Data Gear のメモリを確保 | |
185 * 確保した Data Gear は基本的に破棄可能なものである | |
186 * リニアにメモリを確保し、サイズを超えたら先頭に戻って再利用 | |
187 | |
188 ![Allocator](./pictures/allocation.svg) | |
189 | |
190 # Allocator | |
191 * Allocation に必要な情報を Data Gear に書き込み、Allocator に接続する | |
192 * 生成した Data Gear には Context を介してアクセスすることができるが、Context を直接扱うのは好ましくない | |
193 * Context から値を取り出すだけのメタレベルの Code Gear を用意 | |
194 | |
195 ``` C | |
196 // Meta Code Gear | |
197 __code meta(struct Context* context, enum Code next) { | |
198 // meta computation | |
199 goto (context->code[next])(context); | |
200 } | |
201 | |
202 // Code Gear | |
203 __code code1(struct Context* context, struct Allocate* allocate) { | |
204 allocate->size = sizeof(struct Data1); | |
205 context->next = Code2; | |
206 | |
207 goto meta(context, Allocator); | |
208 } | |
209 | |
210 // Meta Code Gear(stub) | |
211 __code code1_stub(struct Context* context) { | |
212 goto code1(context, &context->data[Allocate]->allocate); | |
213 } | |
214 | |
215 // Meta Code Gear | |
216 __code allocator(struct Context* context, struct Allocate* allocate) { | |
217 context->data[++context->dataNum] = context->heap; | |
218 context->heap += allocate->size; | |
219 | |
220 goto meta(context, context->next); | |
221 } | |
222 | |
223 // Meta Code Gear(stub) | |
224 __code allocator_stub(struct Context* context) { | |
225 goto allocator(context, &context->data[Allocate]->allcate); | |
226 } | |
227 | |
228 // Code Gear | |
229 __code code2(struct Context* context, struct Data1* data1) { | |
230 // processing | |
231 } | |
232 | |
233 // Meta Code Gear(stub) | |
234 __code code2_stub(struct Context* context) { | |
235 goto code2(context, &context->data[context->dataNum]->data1); | |
236 } | |
237 ``` | |
238 | |
239 # TaskQueue | |
240 TaskQueue は Task を管理する。 | |
241 すべての Context で共有され並列にアクセスされる。 | |
242 CAS 命令を利用してアクセスすることでデータの一貫性を保証する。 | |
243 | |
244 * 先頭と末尾の要素へのポインタを持った Queue を表す Data Gear | |
245 * Task と次の要素へのポインタを持った Element を表す Data Gear | |
246 ``` C | |
247 // Code Gear Name | |
248 enum Code { | |
249 PutQueue, | |
250 GetQueue, | |
251 }; | |
252 | |
253 // Unique Data Gear | |
254 enum UniqueData { | |
255 Queue, | |
256 Element, | |
257 }; | |
258 | |
259 // Queue definication | |
260 union Data { | |
261 // size: 20 byte | |
262 struct Queue { | |
263 struct Element* first; | |
264 struct Element* last; | |
265 int count; | |
266 } queue; | |
267 // size: 16 byte | |
268 struct Element { | |
269 struct Task* task; | |
270 struct Element* next; | |
271 } element; | |
272 } | |
273 ``` | |
274 | |
275 # TaskQueue の操作(Enqueue) | |
276 * Enqueue は Queue の最後の要素を取り出し、次の要素に追加する要素を設定 | |
277 * Queue を表す Data Gear が指す末尾を追加する要素に設定 | |
278 * 正しく最後の要素が取り出せたことを保証して末尾の変更を行う必要がある | |
279 | |
280 ``` C | |
281 // Enqueue | |
282 __code putQueue(struct Context* context, struct Queue* queue, struct Element* new_element) { | |
283 struct Element* last = queue->last; | |
284 | |
285 if (__sync_bool_compare_and_swap(&queue->last, last, new_element)) { | |
286 last->next = new_element; | |
287 queue->count++; | |
288 | |
289 goto meta(context, context->next); | |
290 } else { | |
291 goto meta(context, PutQueue); | |
292 } | |
293 } | |
294 ``` | |
295 | |
296 # Persistent Data Tree | |
297 * Data Gear の管理を行う | |
298 * 複数の Context で共有 | |
299 * 一度構築した木構造を破壊することなく新しい木構造を構築するので平行して読み書き可能 | |
300 * 非破壊木構造の基本的な戦略はルートから変更したいノードへのパスをすべてコピーし、パス上に存在しないノードはコピー元の木構造と共有する | |
301 | |
302 ![非破壊木構造](./pictures/tree.svg) | |
303 | |
304 # Persistent Data Tree | |
305 * 木構造を構築するとき最悪なケースでは事実上の線形リストになり、計算量が O(n) となる | |
306 * 挿入・削除・検索における処理時間を保証するために Red-Black Tree アルゴリズムを用いて木構造の平衡性を保つ | |
307 * Red-Black Tree では変更したノードからルートに上りながら条件を満たすように色の変更や木の回転を行う | |
308 * Code Gear の継続では呼び出し元に戻ることが出来ないので Context に辿ったパスを記憶するためのスタックを準備する。 | |
309 | |
310 ```C |