ElixirでIoT#1.3.1：ベンチマークのパラメータを振って性能評価してみた

# はじめに

どうもこんにちは．
[fukuoka.ex](https://fukuokaex.connpass.com/)という技術コミュティにて，**ElixirをIoTボードで動かしたらどうなんの？**というIoT芸を披露しております．

[これまでの連載記事](https://qiita.com/takasehideki/items/8f43f1853ce88cbbe82e#elixirでiot1iotボード上でのelixirphoenix環境構築と性能評価篇)では，IoTボード上でElixirが実行できる環境を構築し，それぞれの性能をベンチマークアプリで評価してきました．
　|> [ElixirでIoT#1.0：IoTボードへのLinux環境の準備](https://qiita.com/takasehideki/items/9e3db412a40659233384)
　|> [ElixirでIoT#1.1：IoTボードへのElixir環境の構築とEEloTツールキットの紹介](https://qiita.com/takasehideki/items/fc570ae92a895caed213)
　|> [ElixirでIoT#1.2：いろいろ分かるベンチマークを整備してみる](https://qiita.com/takasehideki/items/e1dcb4058c7d0b51d554)
　|> [ElixirでIoT#1.3：IoTボードで動いた！Phoenixが立った！性能評価と考察](https://qiita.com/takasehideki/items/0aa644639f81c2ad0bbc)

これまでの性能評価を，下記のようにまとめました．

- IoTボードでもElixirは動く！Phoenixだって立つ！！
- Elixir並列処理はすごい！マイクロアーキよりコア数！！
    - IoTボードでも高性能なものをドンと置くよりもコアをズラッと並べるほうが有利！
    - XU3/A15は最大2.0GHzなのも効いている？
- サーバ性能はネットワーク接続方法も大事なのかも？
    - Ethernet接続で対決させたら違う傾向になるかも
- ZYBOは健闘はしたものの，，，FPGA活用に期待しましょう
- なお消費電力は？？
    - ZYBO << XU3 < RPi3 <<<(超えられない壁)<<< Mac
- [EEloT](https://github.com/takasehideki/EEloT)を使えば性能の比較評価もお手のもの


今回（と次回）は，[連載記事#1.3](https://qiita.com/takasehideki/items/0aa644639f81c2ad0bbc)で実施した評価実験をさらに深掘りしてます．各種ベンチマークのパラメータを振ってみて性能評価してみたいと思います．

# 用意した評価環境

## IoTボード環境


下記３ボード４種類を用意しました．

- [Raspberry Pi 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/)
    - OSは[Raspbian Stretch with Desktop 4.9](https://www.raspberrypi.org/downloads/raspbian/)と[Ubuntu MATE 16.04](https://ubuntu-mate.org/raspberry-pi/)
- [ODROID-XU3](http://www.hardkernel.com/main/products/prdt_info.php?g_code=g140448267127)
    - OSは[ubuntu-16.04-mate-odroid-xu3-20170731](https://odroid.in/ubuntu_16.04lts/)
- [ZYBO](https://japan.xilinx.com/products/boards-and-kits/1-4azfte.html)
    - OSは[Xillinux-2.0](http://xillybus.com/xillinux)

詳細なスペックは[連載記事#1.0](https://qiita.com/takasehideki/items/9e3db412a40659233384#linux%E7%92%B0%E5%A2%83%E3%81%AE%E6%A7%8B%E7%AF%89)をご参照ください．


## ベンチマークアプリ

下記の３種類を用意しました．

- [leibniz_formula.ex](https://github.com/takasehideki/EEloT/blob/master/leibniz_formula.ex)
    - ライプニッツ級数による円周率の計算
    - 浮動小数点演算の性能を評価
- [fibonacci_simple.ex](https://github.com/takasehideki/EEloT/blob/master/fibonacci_simple.ex)
    - フィボナッチ数列の単一プロセス版
    - 整数演算および再帰によるスタック消費時の性能を評価
- [fibonacci_process.ex](https://github.com/takasehideki/EEloT/blob/master/fibonacci_process.ex)
    - フィボナッチ数列のマルチプロセス版
    - 並列処理時の性能を評価

詳細な説明は[連載記事#1.2](https://qiita.com/takasehideki/items/e1dcb4058c7d0b51d554#%E3%83%99%E3%83%B3%E3%83%81%E3%83%9E%E3%83%BC%E3%82%AF%E3%81%AE%E7%B4%B9%E4%BB%8B)をご参照ください．

## ベンチマーク用のソース

性能評価を楽にするために，下記のソースを用意しました．
まぁパラメータを配列にして引数で順に渡してるだけです^^;
なお，最初のパラメータ値が連続しているのは，評価時にキャッシュの影響を除去するためです．まぁまぁ無視できない挙動の誤差がありました．

```measure.ex
defmodule Measure do

  @lf_arg [10, 10, 100, 1_000, 10_000, 100_000, 1_000_000, 10_000_000, 100_000_000]
  def leibniz do
    IO.puts "Measurement of LeibnizFormula start.\n"
    IO.puts "arg,time[us]"
    Enum.each(@lf_arg, fn(i) ->
      {time, _} = :timer.tc(LeibnizFormula, :calc, [i])
      IO.puts "#{i},#{time}"
    end)
  end

  @fs_arg [10, 10, 100, 200, 500, 1_000, 2_000, 5_000, 10_000, 20_000, 50_000, 100_000]
  def fibsimple do
    IO.puts "Measurement of FibonacciSimple start.\n"
    IO.puts "arg,time[us]"
    Enum.each(@fs_arg, fn(i) ->
      {time, _} = :timer.tc(FibonacciSimple, :fib, [i])
      IO.puts "#{i},#{time}"
    end)
  end

  @fm_arg [1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
  @fm_process [37,37,37,37,37,37,37,37,37,37]
  def fibmulti do
    IO.puts "Measurement of FibSolver start.\n"
    IO.puts "arg,time[us]"
    Enum.each(@fm_arg, fn(i) ->
      {time, _} = :timer.tc(Scheduler, :run, [i, FibSolver, :fib, @fm_process])
      IO.puts "#{i},#{time}"
    end)
  end
end
```

# 評価結果

さて今回の評価結果です．

## leibniz.ex

和の上限を`[10, 100, 200, 500, 1_000, 2_000, 5_000, 10_000, 20_000, 50_000, 100_000]`で振ってみました．

![leibniz.jpg](https://qiita-image-store.s3.amazonaws.com/0/240349/f502ef27-2646-aecb-d1de-52b53e6148a0.jpeg)

おぉ見事な線形関係！でもまぁ他に言うことはありません:laughing:
なおグラフの縦軸・横軸は対数表記にしています．

## fibonacci_simple.ex

数列の項数を`[10, 100, 200, 500, 1_000, 2_000, 5_000, 10_000, 20_000, 50_000, 100_000]`で振ってみました．

![fib_simple.jpg](https://qiita-image-store.s3.amazonaws.com/0/240349/8e8983d6-a22c-cd50-b7e1-bcd46903da57.jpeg)

こちらはちょっとばらつきがありますが，やはりお見事な相関関係です．なおこれも縦軸・横軸は対数表記です．
項数が小さいときはODROID-XU3のほうがRP3Bより優れていますが，大きくなると優位性が逆転しました．つっても誤差の範囲内です．再帰処理なのでカーネルによるメモリ管理がこの傾向に影響してくるのかもしれません．
ちなみにZYBOでは`100_000`の時にheapメモリ不足による実行エラーが発生しています．

## fibonacci_process.ex

37までの数列を10個同時に求める設定として，並列プロセス数を1から16まで順に振ってみました．

![fib_process.jpg](https://qiita-image-store.s3.amazonaws.com/0/240349/a83780ab-9920-aada-7081-ef33bc93433d.jpeg)

RP3BとZYBOについては，それぞれの物理コア数である4と2までは，プロセス数に比例して性能向上していることが分かります．Elixir/Erlangの並列性能をうまく発揮できていますね．

8コアのODROID-XU3についてはちょっと気になります．他のIoTボードよりも優れた性能を示していますが，甘めに見ても6プロセス辺りまでで並列性能の効果が頭打ちになっています．
ODROID-XU3に搭載されているExynos 5 Octa 5422では，4コアのCortex-15と4コアのCortex-A7は別々のクラスタで構成されていて，それらがL2キャッシュを介して密結合されています．このSoCアーキテクチャの特性のために，全コア数ほどの並列性能を発揮できなかったのかもしれません．

# まとめ

- [EEloT](https://github.com/takasehideki/EEloT)ベンチマークアプリのパラメータを振って性能評価してみました
    - パラメータにうまく比例した性能を発揮！
    - コア数についての並列性能もお見事！でもSoCアーキには要注意！？

よろしければ「いいね！」いただけるととっても嬉しいです．
「ElixirでIoT芸」に需要あるのか露頭に迷っている書き手の励みになります:thumbsup: