***********************************************
セッションS1-d 分科会
テーマ :mruby/cによるマルチプログラミングの概要
講師 :田中 和明(九州工業大学)
日時 :2018/08/30 21:00 - 22:30
参加人数:約35名
************************************************

■概要
・マルチプログラミング
・mrubyとmruby/c

複数のプログラムを走らせたい
⇒普通はOSの仕事であるが、OSなしでやりたい!
(OSはリッチな環境が必要で、OSのフル機能は必要ないような場面)


■自己紹介
・田中和明(九州工業大学 情報工学部)
・教育-情報基礎、プログラミング、データ構造とアルゴリズムなどを教えている。
(ほとんどC言語)
・研究-・組込みシステム(mruby、全体の7割) 
・ブロックチェーン技術(をIoTで利用する)
・LPWA、光学測量に関する共同研究

・mruby:2010年に経済産業省にお金をもらって開発した
オープンソースになったが、使い方が分からなかったり、そもそもツールも少
なくあまり使ってもらえなかった。
 ⇒ お金をもらって、ツールを増やして、小型化にfocusし、ここ半年で
   ようやく普及してきた。
    もうすでに、製品に使われている。(数として、一番多いのはPS4のゲームソフトでの利用)
    ハードウェアではなく、システムやソフトウェアやゲームへの組込みに
使われて始めた。

 この現状でサポートできないエリア、特にIoTで重要な領域を狙ったのが、
 mruby/cにプロジェクトになる。基本的にはmrubyと一緒。
 VMに工夫がしてあり、非常に小型化できたり、
 マルチプログラミングできたりする。


・マルチプログラミングとは:
複数の機能を実装するとプログラムが複雑化する
  -異なるタイミングでそれぞれの機能を動かす
  -機能ごとに実装を分離
  -セキュリティ
  -保守性

シングルでやろうとタイミングを気にする必要や、お互いを考える必要や、
OSの必要性がでてきて大規模になる可能性がある

例:赤色LEDを1秒間隔で点滅させる(mrubyプログラム)
 
 while true do
  output 0,1
  sleep_ms 1000
  output 0,0
  sleep_ms 1000
 end

output : GPIO出力
sleep_ms : スリープ


問題
:赤色LEDを1秒間隔で点滅させる
:緑色LEDを0.1秒間隔で点滅させる

・シングルプログラミングの場合

t = 0
while true do
 # 緑色LED
 if t%2 == 0 then
  output 7, 0
 else
  output 7, 1
 end
 

 # 赤色LED&リセット
 if t == 10 then
  output 0, 1
 elsif t >= 20 then
  t = 0
  output 0, 0
 end
 sleep_ms 100
 t += 1
end

これは可能だが、考えるのが大変
      ↓
・マルチプログラミングを実現するための技術
 ・割込み
 ・スレッド
 ・マルチタスク(プロセス)

これらの技術を使いつつ、簡単に実装したい→mruby/cのマルチプログラミング

while true do   while true do
 output 7, 1    output 7, 1
 sleep_ms 100 sleep_ms 100
 output 7, 0 output 7, 0
 sleep_ms 100 sleep_ms 100
end end


mruby/cのマルチプログラミングでは、
VMが二つのプログラムを切り替えながら実行している
これが本日の話題

<質疑応答>
質問:
・平行して動いているが、始まるタイミングはそこまで気にしてない?
回答:
・二つのプログラムがそれっぽく同時に動いている感じ
 実際には少しずつ実行を切り替えている。現実的にはタイミングの問題や排他制御が必要。
 今回は、各LED(GPIO)のアクセスは独立しているので、排他制御は不要

 
・mruby
-Rubyを軽量化したもの
  ~Rubyにほぼ準拠しており、Rubyの開発効率を組込みソフト開発へ活かす
-Rubyとの互換性を重視
~Ruby技術者が組込み開発できる
 -消費メモリは400KB程度

割と実績がある。

mrubyの利用事例:ネットラークル−タ(IIJ社)
ゲーム(スクエアエニックス、SidMeier's)
Apacheモジュール(OSS)
ETロボコン(アフレル社、ほか)
GUIライブラリ(ILC社)

<質疑応答>
質問:
・なんでmrubyは利用されたのか?
回答:
・modmruby:Rubyでやりたかったがでかいので、軽いmrubyが導入された
・ルータ:軽いmrubyがオープンソース化されて採用された。ルータの設定などで使う
・ゲーム:業界がスプリクト言語をほしがってた。
    外注との言語を切り分けたいため(影響範囲を限定したい)。

・mruby/c
 -mrubyをさらに軽量化したもの ~40KB程度
 ワンチップマイコンでの動作を想定したもののため、資源が限られる
  (実際には20KBぐらいで動く、あとはプログラムが消費するメモリに依存する)
  (最小、例えば hello world であれば、10KB程度でも動く)
 -Rubyとの互換性というよりもrubyっぽいものを考えており、
 小型化を重視している。
-最小限のクラスライブラリしか実装されてないため、サポートされてない
 Rubyの機能は多数ある
-OSを必要としない

<質疑応答>
質問:
・実装するかどうかの判断の基準は?
回答:
・基準は特にない。依頼があれば検討して実装するか判断する。
 個人に依存する。
 
質問:
・コンパイラによる最適化は難しい?
回答:
・mrubyとmruby/cのコンパイラは同じで、まつもとさんに聞いてほしい。


rubyがソースコードをそのままインタプリターのかけて実行するのに対し、
mrubyとmruby/cはソースコードをコンパイルし、mrubyバイトコードとし、
それぞれのVMで実行させる。これによりメモリを抑えることができる。
mruby VMとmruby/c VMは動きは一緒、サポートされるクラスやメソッドなどが違う


■mruby/cのポイント

・OSを必要としない
・OSが提供する機能を持つ
 -マルチプログラミング
  複数プログラムのコンカレント実行
 -メモリ管理
 -排他制御
・ユーザプログラムとして実行する(特権命令は必要ない)

・mrubyのバイトコード
  →ソースコードのコンパイルにより生成される。
          アセンブリに近い言語
各レジスタはオブジェクトのインスタンスが入る
           SEND(C言語の関数呼び出し):メッセージパッシングを行う

  このコードは機種に依存しないのでどのデバイスでも動く。

・mruby VM
VMがバイトコードを実行する。
VMを作ればどこでも実行することができる。

mruby/c VMのアイデア
・複数のプログラム(複数のバイトコード)を実行する。

loop do
 for i=1 to N do
  current_program = program[i]
  instruction = Fetch(current_program)
  Execute(instruction)
 end
end

1命令ごとに実行プログラムをスイッチ。可能だがオーバヘッドが大きくなるのでやらない。
実行効率の問題

・実行効率が悪いので、
 いくつかのバイトコードを実行する。

loop do
 for i=1 to N do
  current_program = program[i]
  for j=1 to M do
   instruction = Fetch(current_program)
   Execute(instruction)
  end
 end
end

パフォーマンスは上がる
問題:実行の公平性が保証されない(命令ごとに実行時間が異なるから)


・実行の公平性
・プログラム間で実行時間が公平ではない。
 時間が来たら切り替える→ある程度の公平性は保たれる

loop do
 for i=1 to N do
  current_program = program[i]
  start_time = GetCurrentTime()
  while GetCurrentTime() < (start_time + TIME_SLICE) do
   instruction = Fetch(current_program)
   Execute(instruction)
  end
 end
end

しかし、これは重い(時刻の取得が重い!)。あくまで仮想的なプログラム。
そのため、、

・mruby/cの実装では、
・タイマー割込みが使える場合は、
 割込みでプログラムを切り替える。

割り込み発生時に、実行中のプログラムの flag に1を入れる
⇒次の命令を実行する前にフラグをチェックする
⇒切り替わる

この処理は軽い

Result
・Execution time
-Calculate 32th Fibonacci number using recursion
複数のフィボナッチ数計算をコンカレントに実行している
割込みだと単体(フルパフォーマンス)と同じような結果が得られた。

・サンプルプログラムの紹介

スイッチが押されると状態が変化する
0⇒1⇒0⇒1→0→1
スイッチが押されてから500msは入力を無視する
状態に応じてLEDの点滅をする

シングルプログラムで考えると難しい。
→ 2つのプログラムにすると簡単

(1) スイッチが押されたら、状態を変化させる(同時に500msの入力禁止=プログラムのスリープ)
(2) 状態に応じてLEDを点滅させる

状態0:50msの点滅
状態1:500msの点滅
状態2:1sの点滅

<質疑応答>
質問:
・状態が変わったとき、点滅の途中はどうするか?
回答:
・排他制御とかを入れるとか、、、
⇒ コメント:使いにくそう、、、
・global変数によってプログラム間の通信ができる。
 アトミックにできるため排他制御は必要ない。
 これが現状のmruby/c


質問:
・優先度があればどう動くかがわかるのでは?
少しコードを入れると、優先度スケジューリングできそう
回答:
・2個以上の場合、優先度がないとどうなるかわからなそう、、、
 シンプルさはどこまで保たれるのか
⇒rubyを使うぐらいには保たれる
     VM‎に負担があるいくだけだから


指摘:ドキュメントがない


■まとめ
なし