オタク日記
(Mac と Linux, RasPi, 2019Q3)

目次

2019-07-10 (Wed): Raspbian Buster (2: CPU Temp, Clock)
2019-07-03 (Wed): Raspbian Buster (1: Install, PyVenv)

古い日記:
2019Q2   2019Q1  
2018Q4   2018Q3   2018Q2   2018Q1  
2017Q4   2017Q3   2017Q2   2017Q1  
2016Q4   2016Q3   2016Q2   2016Q1  
2015Q4   2015Q3   2015Q2   2015Q1  
2014Q4   2014Q3   2014Q2   2014Q1  


2019-07-10 (Wed): Raspbian Buster (2: CPU Temp, Clock)

二台有る 3B+ の両方を Buster にしてしまう前に、片方だけに heatsink が付いているとう状況を利用して、 集中して CPU を使った場合に、どれくらい CPU 温度が上昇するか確認してみた。 (要するに「(あのちゃっちい) heatsink が本当に要るの?」を確認したい、と。)

CPU Package が金属製になった

3B+ になって一番先に違いに気付くのは、その CPU のパッケージが金属製になった事。 これによって、チップ内の実際に熱を発生する部分の熱を急速に拡散できるみたいで、 CPU の clockspeed を上げて運転できる期間を延長できる、としている。

実際 Medium Technology の Benchmarking の記事 にある見事な thermograph を見れば一目瞭然:

RasPi3B+ and USB Card Reader
RasPi 3 の基板上面の Thermograph
RasPi3B+ and USB Card Reader
RasPi 3 B+ の Thermograph

それほど一目瞭然でない人のために解説をしておくと、 左側の RasPi 3 の基板では、SoC チップのパッケージ表面の一箇所に非常に温度の高い (> 90℃) ところがあり、その下のチップは更に温度が上がっているだろうと予想される。

それに対して、右側の RasPi 3B+ の SoC チップの表面は、一様に高くなる事で、 極端に高くなっているところがない。これより、当然 (肝心の) チップ表面も、 かなり低く保たれているだろうと予測される。また、 基板の他の部分にも一様に熱が伝わって暖かくなっている事が見て取れる。 実際、連続運転中、3B+ の (SoC から遠い) HDMI コネクタに触ってみると、3B と比較してかなり熱くなっているのが解る。

測定系の概要

被測定サンプル

Raspi23b (ヒートシンク有り、但し SoC のみ)、Raspi24: (ヒートシンク無し)。 いずれも、白いケースに入れて、蓋をした状態で測定する。参照用に RasPi13 (3B) も火入れをして走らせておいた。

RasPi13/23/24 outlook
Fig-1, RasPi23, RasPi24, 及び RasPi13 (3B) の外観

測定方法

コア温度とクロックの測定は、Raspbian 附属の vcgencomd を用いて、 sudo vcgencmd measure_tempsudo vcgencmd measure_clock armのようにして測定する。 これらを、約 2 秒毎に走らせる Python Script を書いて実行した。

(pve37) fukuda@raspi24:~/Work-current/MeasureTemp% ./meas_temp.py
[sudo] password for fukuda: 
.....
#! /usr/bin/env python                         #1)
import datetime, sys, time, getpass
from subprocess import run, PIPE

def main(argv):

    if len(argv) >= 2 and argv[1]:
        duration = int(argv[1])
    else:
        duration = 600

    finish = datetime.datetime.now() \
                + datetime.timedelta(seconds=duration)

#    password = getpass.getpass()                                               

    fpd = open("temp_clock.dat", "w")

    while(1):
        current = datetime.datetime.now()
        if current > finish:
            fpd.close()
            break
        #2)
        proc = run(["sudo vcgencmd measure_temp"], stdout=PIPE, 
                   shell=True)   
        temp = proc.stdout.decode("utf-8").split("=")[-1].split("'")[0]
        proc = run(["sudo vcgencmd measure_clock arm"], 
                   stdout=PIPE, shell=True)
        clock = int(proc.stdout.decode("utf-8").split("=")[-1])/1.0e6
        curr_short = current.time().replace(microsecond=0)
        print(f"{curr_short} {temp} {clock:.2f}")
        fpd.write(f"{curr_short} {temp} {clock:.2f}\n")

        time.sleep(2)

    sys.exit(0)

if __name__ == "__main__":
    main(sys.argv)
  1. #1) PyVenv に入った状態で、このスクリプトを実行すると、 この行により Python-3.7.3 が起動される。
  2. #2) 実行時、標準入出力がターミナルだと (つまり、script を foreground で実行すると) sudo を実行時に password を求めるプロンプトを表示する。(最初の一回だけ。)

CPU 負荷は Byte UnixBench を使用する。Github からソースを取ってきて make, その後、arithmetic グループを、1 コア使用と 4 コア使用を指定して実行。

fukuda@raspi24:~% cd Work-current 
fukuda@raspi24:~/Work-current% git clone https://github.com/adlucas/byte-unixbench
fatal: destination path 'byte-unixbench' already exists and is not an empty directory.
fukuda@raspi24:~/Work-current% cd byte-unixbench/UnixBench 
fukuda@raspi24:~/Work-current/byte-unixbench/UnixBench% make
make distr
make[1]: Entering directory '/home/fukuda/Work-current/byte-unixbench/UnixBench'
.....
make programs
.....
fukuda@raspi24:~/Work-current/byte-unixbench/UnixBench% ./Run -c 4 arithmetic
.....
4 x Arithoh  1 2 3

4 x Arithmetic Test (short)  1 2 3 .....

両者を統合するスクリプトを書くべきところ、直ぐにはやり方を思い出せなかったので、 別々に ssh login して独立して走らせた。

測定結果

負荷の重さへの依存性

RasPi24 arithmetic 1/4 cores
Fig-2, RasPi24 の CPU 温度の負荷 (使用コア数) への依存性

CPU core を一つだけ動かす程度の負荷では、CPU 温度は 65℃ 程度までしか上がらないが、 4 core をフル稼働させると、80℃付近まで上昇する (しかも、まだ飽和していない)。

Heatsink の有無

上記の結果、Soft shut-off を起動する温度の 85℃ まで 5℃ 程度の余裕が無い事が解ったので、 これに heatsink をつけて、どれくらい改善されるかを見る。

RasPi24 arithmetic 1/3 cores
Fig-3, Heatsink の有無による温度上昇の比較

結果は、3 ~ 5℃ 程度の改善が見られる、となった。継続して 4 core をフルに使い続けるような用途には、とりあえず heatsink を付けておいた方が安全だろう。

CPU Clock

RasPi 3B+ のドキュメントによると、アイドル時は 600 MHz のクロックで動き、 負荷がかかると、1.4 GHz, その後 CPU 温度が上昇すると、1.2 GHz まで落ち、 85℃ まで上がった時点で、600 MHz に落すとある。

しかし実際には、CPU クロックは複雑な動きをしている。

RasPi24 arithmetic 1/3 cores
Fig-4, CPU 温度と CPU クロック。

温度とクロック周波数を測定するルーチン自体が負荷になっている事もあり、 なかなか解釈が難しいが、敢えて纏めると:


2019-07-03 (Wed): Raspbian Buster (1: Install, PyVenv)

Debian より前に Raspbian Buster……

何故か本家の Debian の Buster が testing のままなのに、 Raspbian では、2019-06-20 付けで Buster が (正式?) リリースとなった。 Raspberry Pi 4 B の発売が 2020 年になると言われていたのが、 早まったらしいので、それに合わせて (慌てて?) 出したのだろう。

だとすると、 私自身は少なくとも当面は、目下のプロジェクトを RasPi 3B+ で進めるつもりなので、 今 Buster に手を出すのは、いかにも「一丁噛み」みたいだが、 この Buster は、Python のデフォルトが -3.7 になっている、 という噂につい乗せられて……

それにしても、つい最近、「Python-3.7.3 ソースからコンパイルして、 それで -venv を作って……」 なんてオタク趣味に走ったばかりなのに、やっぱり軽率だったかな。 しかしまあ、だからこそ触ってみずにはおれない、とも言えるか :-) とりあえず、PyVenv を構築して、その後、Linphone が走るのを確認するところまでは、 手早く確認しておこう (ダメだったら Stretch にすぐ戻る!ゼッタイ!)

インストール・基本設定

「Raspbian Light を WiFi だけを使って最速でインストールする」手順に関しては、 何度も書いて、段々洗練されてきている (多分 :-)。今回も 前回の手順 (基本設定) と、同 (WiFi 設定) がそのまま適用できた。

異なるのは、対象になる RasPi が、raspi24 という ID なので、 Raspbian の hostname を、'raspi24' にしたくらいのもの。従って、 falcon からの ssh login command、RasPi の prompt は以下のようになる。(Zsh の設定によって、prompt に hostname が色分けして表示される。)

fukuda@falcon:~% ssh raspi24
fukuda@raspi24:~% 

Backup のために、rpi-clone をインストールして、USB cardreader を挿し、initialize -> sync を開始。

fukuda@raspi24:~% git clone https://github.com/billw2/rpi-clone.git
fukuda@raspi24:~% ls rpi-clone 
LICENSE  README.md  rpi-clone*  rpi-clone-setup*
fukuda@raspi24:~% sudo cp rpi-clone/rpi-clone /usr/local/sbin/
fukuda@raspi24:~% sudo cp rpi-clone/rpi-clone-setup /usr/local/sbin/ 
fukuda@raspi24:~% sudo rpi-clone -f sda
.....
Done with clone to /dev/sda
   Start - 17:45:36    End - 17:58:04    Elapsed Time - 12:28
.....

問題なく終ったが、今回何故か 12 分半もかかってしまった (前回は 5 分弱)

以降は、時折

fukuda@raspi24:~% sudo rpi-clone sda

とやって、incremental backup (増分バックアップ) を取っている。 Buster でも、問題なく sync が取れているようだ。

PyVenv 環境を作る

fukuda@raspi24:~% sudo apt-get install python3-venv
fukuda@raspi24:~% python3.7 -m venv pve37
fukuda@raspi24:~% cd pve37
fukuda@raspi24:~/pve37tmp% . bin/activate
(pve37) fukuda@raspi24:~/pve37% pip install --upgrade pip pip-tools
.....
Successfully installed click-7.0 pip-19.1.1 pip-tools-3.8.0 six-1.12.0
(pve37) fukuda@raspi24:~/pve37% pip install ipython
.....
Successfully installed backcall-0.1.0 decorator-4.4.0 ipython-7.6.0 \
    ipython-genutils-0.2.0 jedi-0.14.0 parso-0.5.0 pexpect-4.7.0 \
    pickleshare-0.7.5 prompt-toolkit-2.0.9 ptyprocess-0.6.0 \
    pygments-2.4.2 traitlets-4.3.2 wcwidth-0.1.7

NumPy

ネイティヴの Python-3.7 を使って、PyVenv (venv) を作るんだから、 まさか Numpy でひっかかるとは思わなかった……しかも、% pip install は通るのに、それを Python から import できないという、とても不可解な現象にぶち当った。

あまりの事に、いっそ Python を source から入れてみるか、などと脇道に逸れたが、 結局それも、% make test を通るようにできず断念。

また PyVenv に戻っていろいろやってみた。結果、1) 無事 import できたが、超低速 linalg, 2) OpenBLAS に替えて、速くなった、 というステップを踏んでインストール完了、となったのだが、 今度は、上の「import できない」が再現できない。なので、 「必要十分条件」になっているか自信がないが、ともあれ、

(pve37) fukuda@raspi24:~/pve37% sudo apt install python3-dev libatlas-base-dev
(pve37) fukuda@raspi24:~/pve37% pip install numpy
(pve37) fukuda@raspi24:~/pve37% ipython 
Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.6.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import numpy as np                                                      

In [2]: A = np.random.rand(1024, 1024)                                          

In [3]: %timeit B = np.linalg.inv(A)                                            
10 s ± 5.71 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
In [5]: %timeit C = np.fft.fft2(A)                                              
561 ms ± 7.28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

これは、OpenBLAS がリンクされていないのは明らかなので、とりあえず それらのライブラリを % apt install する。

(pve37) fukuda@raspi24:~/pve37% sudo apt install libopenblas-dev libopenblas-base
.....
update-alternatives: using /usr/lib/arm-linux-gnueabihf/openblas/libblas.so.3 to provide /usr/lib/arm-linux-gnueabihf/libblas.so.3 (libblas.so.3-arm-linux-gnueabihf) in auto mode
update-alternatives: using /usr/lib/arm-linux-gnueabihf/openblas/liblapack.so.3 to provide /usr/lib/arm-linux-gnueabihf/liblapack.so.3 (liblapack.so.3-arm-linux-gnueabihf) in auto mode
Setting up libopenblas-dev:armhf (0.3.5+ds-3+rpi1) ...
update-alternatives: using /usr/lib/arm-linux-gnueabihf/openblas/libblas.so to provide /usr/lib/arm-linux-gnueabihf/libblas.so (libblas.so-arm-linux-gnueabihf) in auto mode
update-alternatives: using /usr/lib/arm-linux-gnueabihf/openblas/liblapack.so to provide /usr/lib/arm-linux-gnueabihf/liblapack.so (liblapack.so-arm-linux-gnueabihf) in auto mode
Processing triggers for libc-bin (2.28-10+rpi1) ... 

ここで、update-alternative と称して、あまり見かけない動作をしているが、 これはどうも、新たに入った /openblas/libblas.so.3 他を、 既存の libblas.so.3 にリンクを張っているようだ。つまり、それを link する側の numpy モジュールの方には何の変更もなく、OpenBLAS を使えるようなる、という事。実際、この後、numpy を再インストールする事なく、 ipython で確認すると、

(pve37) fukuda@raspi24:~/pve37% ipython
Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.6.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import numpy as np                                                      

In [2]: np.show_config()                                                        
.....
atlas_blas_info:
    language = c
    define_macros = [('HAVE_CBLAS', None), ('NO_ATLAS_INFO', -1)]
    libraries = ['f77blas', 'cblas', 'atlas', 'f77blas', 'cblas']
    library_dirs = ['/usr/lib/arm-linux-gnueabihf']
accelerate_info:
  NOT AVAILABLE
blas_opt_info:
    language = c
    define_macros = [('HAVE_CBLAS', None), ('NO_ATLAS_INFO', -1)]
    libraries = ['f77blas', 'cblas', 'atlas', 'f77blas', 'cblas']
    library_dirs = ['/usr/lib/arm-linux-gnueabihf']
.....
atlas_info:
    language = f77
    libraries = ['lapack', 'f77blas', 'cblas', 'atlas', 'f77blas', 'cblas']
    library_dirs = ['/usr/lib/arm-linux-gnueabihf']
    define_macros = [('NO_ATLAS_INFO', -1)]
lapack_opt_info:
    language = f77
    libraries = ['lapack', 'f77blas', 'cblas', 'atlas', 'f77blas', 'cblas']
    library_dirs = ['/usr/lib/arm-linux-gnueabihf']
    define_macros = [('NO_ATLAS_INFO', -1)]

In [3]: A = np.random.rand(1024, 1024)                                          

In [4]: %timeit B = np.linalg.inv(A)                                            
1.13 s ± 478 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

要するに、np.show_config() の出力は変化ない (つまり、OpenBLAS は表面上はリンクされてない) のに、 np.linalg の計算速度は約 10 倍になっている、という事。

LibROSA

これも単に % pip install librosa としただけではダメだったが、前回の経験もあり、 それ程右往左往しなくて済んだ。

(pve37) fukuda@raspi24:~/pve37% sudo apt install llvm   
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  binfmt-support libllvm7 llvm-7 llvm-7-dev llvm-7-runtime llvm-runtime
Suggested packages:
  llvm-7-doc
The following NEW packages will be installed:
  binfmt-support libllvm7 llvm llvm-7 llvm-7-dev llvm-7-runtime llvm-runtime
(pve37) fukuda@raspi24:~/pve37% pip install cython
(pve37) fukuda@raspi24:~/pve37% pip install librosa
.....
Successfully installed audioread-2.1.8 joblib-0.13.2 librosa-0.6.3 llvmlite-0.29.0\
 numba-0.44.1 resampy-0.2.1 scikit-learn-0.21.2 scipy-1.3.0

最初の llvm のインストールはこれだけで良い。deb パッケージとしては、llvm-3.7 から -9 まで揃っているが、そのうち -7 がインストールされる。で、librosa のインストールの際に、 llvmlite が dependency としてインストールされるが、 それと問題なくリンクされるようだ。

また、pip install で個別にインストールする必要があるのは cython のみ。 まだ完璧とは言えないが、PyPI も deb library もパッケージングはかなり進歩しているようだ。 (でも、何故最初から OpenBLAS を使う事にしないのか不思議ではある。)

LibROSA の処理の一つ、effect.pitch_shift のパフォーマンスを調べてみた。

(pve37) fukuda@raspi24:~/pve37% ipython
Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.6.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import librosa                                                          

In [2]: audio_path = '/home/fukuda/katou.wav'                                   

In [3]: y, sr = librosa.load(audio_path)                                        

In [4]: %timeit y_shift  = librosa.effects.pitch_shift(y, sr, n_steps=-6)       
10.5 s ± 25 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [5]: !sudo vcgencmd measure_temp                                             
[sudo] password for fukuda: 
temp=60.7C

In [6]: !sudo vcgencmd measure_clock arm                                        
frequency(45)=1200000000

In [7]: %timeit y_shift  = librosa.effects.pitch_shift(y, sr, n_steps=-6)       
10.5 s ± 5.97 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

一方で、 raspi23b の Raspbian Stretch の無理くりインストールだと

(pve37) fukuda@raspi23b:~/pve37% ipython
Python 3.7.3 (default, Jun  1 2019, 16:32:57) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.5.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import librosa                                                          

In [2]: audio_path = "/home/fukuda/Work-current/SampleVoices/katou.wav"         

In [3]: y, sr = librosa.load(audio_path)                                        

In [4]: %timeit y_shift  = librosa.effects.pitch_shift(y, sr, n_steps=-6)       
17.1 s ± 33.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [5]: !sudo vcgencmd measure_clock arm                                        
[sudo] password for fukuda: 
frequency(45)=1200000000

In [6]: !sudo vcgencmd measure_temp                                             
temp=59.1C

In [7]: %timeit y_shift  = librosa.effects.pitch_shift(y, sr, n_steps=-6)       
17.1 s ± 17.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

であったから、17 sec から 10 sec へと倍近い性能向上と言える。 (effects.pitch_shift では、sfft (数 100 ポイント程度の短かいデータにその都度窓函数を掛けて FFT) を多数回繰返すあたりが、処理の負荷を決めていると思われるが、 fft.fft2() では、両者でほぼ同等の性能だったので、 この差は少し不思議。)

ただ、iPython の立ち上がりに要する時間が、Buster では Stretch の半分くらいになっているので、Stretch では NumPy 以外のところにボトルネックが有るのかも知れない。

Pip-tools で管理を始める

macOS (MacPorts) でも、Ubuntu-18.04 でも、PyVenv でのパッケージのインストールやアップデートに失敗する事は殆んど無いので、 大抵は、requirements.in に必要な、package をずらずら書いて、% pip-compile で、 requirements.txt に dependency を含めた package のリストを作り、その後、pip-sync で、実際のインストールもしくは、アップグレードをする事にしている。 (これは確かに、便利で確実!)

Raspbian Stretch 上での PyVenv は、どうも PyPI の (もしくは、Raspbian の) 依存関係の取り込み?がうまく行ってないようなので、 一つづつ pip で入れて行ったが、今回もそれを踏襲した。 しかし、一応環境が整ったので、これも pip-tools での管理に移行する。

(pve37) fukuda@raspi24:~/pve37% pip freeze > pip-freeze     #1)
(pve37) fukuda@raspi24:~/pve37% cat pip-freeze        
audioread==2.1.8
backcall==0.1.0
Cython==0.29.10
decorator==4.4.0
ipython==7.6.0
ipython-genutils==0.2.0
.....
numpy==1.16.4
.....
scipy==1.3.0
.....
(pve37) fukuda@raspi24:~/pve37% pip install pip-tools
(pve37) fukuda@raspi24:~/pve37% emacs requirements.in       #2)
(pve37) fukuda@raspi24:~/pve37% cat requirements.in 
numpy
scipy
ipython
cython
librosa
(pve37) fukuda@raspi24:~/pve37% pip-compile --no-annotation #3)
(pve37) fukuda@raspi24:~/pve37% diff pip-freeze requirements.txt  
.....                                                       #4)
3c11
< Cython==0.29.10
---
> cython==0.29.11
5d12
< ipython==7.6.0
6a14
> ipython==7.6.0
16d23
< pkg-resources==0.0.0
19c26
< Pygments==2.4.2
---
> pygments==2.4.2
25a33,35
> 
> # The following packages are considered to be unsafe in a requirements file:
> # setuptools==41.0.1
(pve37) fukuda@raspi24:~/pve37% pip-sync                    #5)
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting cython==0.29.11 (from -r /tmp/tmp_xgenhl7 (line 1))
  Using cached https://files.pythonhosted.org/packages/..../Cython-0.29.11.tar.gz
Installing collected packages: cython
  Found existing installation: Cython 0.29.10
    Uninstalling Cython-0.29.10:
      Successfully uninstalled Cython-0.29.10
  Running setup.py install for cython ... done
Successfully installed cython-0.29.11 

ここに:

  1. #1) % pip freeze で、現在のインストール済みパッケージのリストを作製
  2. #2) (dependency でない) 明示的に要求したパッケージのリストを作製
  3. #3) 上のリスト (requirements.in) から、全ての dependency を含む requirements.txt を作る。
  4. #4) 現在のリスト (pip-freeze) と、これからインストールされる requirements.txt の差を取る。大文字小文字の差の他には、 Cython のバージョンが違っているだけ。
  5. #5) 現状のインストールの状態を、requirements.txt に合致させる。 (結果として、Cython が 0.29.10 から 0.29.11 にアップグレードされた。)

たまたま、Cython が、当初のインストールから、pip-compile の実行までの間にアップグレードされていたので、このような実行結果となった。 これ以降は、

(pve37) fukuda@raspi24:~/pve37% emacs requirements.in
(pve37) fukuda@raspi24:~/pve37% pip-compile --upgrade
(pve37) fukuda@raspi24:~/pve37% pip-sync

を繰返すだけで良い。(勿論、requirements.in の編集は「必要が有れば」で良い。)

という事で、Raspbian Buster への乗換えは (今のところ) 正解だったようだ。


164/1,384,483 Valid CSS! Valid HTML 5.0
Taka Fukuda
Last modified: 2019-07-10 (Wed) 16:10:18 JST