忍者ブログ

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

[Python 3] デコレータで実行時間を測る例のやつ


デコレータ実装での実行時間計測は、何も手を打たないと再帰関数でおかしな結果がでる

デコレータで実行時間を測る例のやつ (笑) を色々試してて気になった点や欲しい機能とかをいじってたらなんか後々使えそうな代物ができたので、docstring の書き方の練習も兼ねて公開してみることに。

  • どこかで sp = SimpleProfiler() とかして、
    with sp:
        pass
    とするか、
    @sp.profile
    def foo():
        pass
    とすれば sp に測った実行時間やらカウントやらが記録されます。
  • 後は時期を見計らって sp の各プロパティを読んで下さい。
    また、reset() で測った記録をリセットできます。
  • Python インタプリタに直接食わせると、フィボナッチ関数 (キャッシュ無しと有り) をプロファイルするデモを行います。
  • Python 3.5 (Debian Stretch に入ってるバージョン) あたりから使えると思います。
    当方ではとりあえずこれ書いている時点で最新の Raspbian で使えるやつ (3.5.3) と Windows版 (3.7.3) で開発・動作確認をしてあります。

ソースコード

使いたいという奇特な方は下記をコピペして simpleprofiler.py とかで各自保管して下さい。MITライセンスで扱って貰えば特に連絡などは要りません。

#!/usr/bin/env python3

# simpleprofiler.py - Simple profiler
#
# Copyright (c) 2019 Takayuki 'January June' Suwa
#
# This software is released under the MIT License.
#  https://opensource.org/licenses/mit-license.php

# PEP 8 (for lexical)
#000000001111111111222222222233333333334444444444555555555566666666667777777777
#234567890123456789012345678901234567890123456789012345678901234567890123456789

# PEP 8 (for text)
#00000000111111111122222222223333333333444444444455555555556666666666777
#23456789012345678901234567890123456789012345678901234567890123456789012

"""Simple profiler."""

try:
    from time import perf_counter_ns as _perf_counter_ns
    _clock = lambda: _perf_counter_ns() * 1e-9
except ImportError:
    try:
        from time import perf_counter as _clock
    except ImportError:
        from time import clock as _clock

class SimpleProfiler(object):
    """Simple profiler implementation, as context mananger."""

    __slots__ = "__started", "__elapsed_time", "__nested_level", \
            "__entered_count", "__checked_count", "__raised_count", \
            "__clicked_count"

    def __init__(self):
        self.__started, self.__elapsed_time, self.__nested_level, \
                self.__entered_count, self.__checked_count, \
                self.__raised_count, self.__clicked_count = 0.0, 0.0, 0, 0, 0,\
                0, 0

    def __repr__(self):
        return "%s(%fsec, %d, %d, %d, %d)" % (self.__class__.__name__,
                self.__elapsed_time, self.__entered_count, self.__checked_count,
                self.__raised_count, self.__clicked_count)

    @property
    def elapsed_time(self):
        """Return the accumulated value of the elapsed time in second
        around the region of the code, inside of this context.
        """
        return self.__elapsed_time

    @property
    def entered_count(self):
        """Return the accumulated value of the counter which is
        incremented by 1 when this context is entered.
        """
        return self.__entered_count

    @property
    def checked_count(self):
        """Return the accumulated value of the counter which is
        incremented by 1 when each time check has finished.
        """
        return self.__checked_count

    @property
    def raised_count(self):
        """Return the accumulated value of the counter which is
        incremented by 1 when each uncaught exception has been raised.
        """
        return self.__raised_count

    @property
    def clicked_count(self):
        """Return the accumulated value of the counter which is
        incremented by 1 when each 'click()' method has been called.
        """
        return self.__clicked_count

    def click(self):
        """Increment the number of times this method was called, by 1.
        """
        self.__clicked_count += 1

    def reset(self):
        """Reset the elapsed time and each counters, to the initial
        state.
        """
        self.__elapsed_time, self.__nested_level, self.__entered_count, \
                self.__checked_count, self.__raised_count, \
                self.__clicked_count = 0.0, 0, 0, 0, 0, 0

    def __enter__(self):
        """Enter this context.

        When re-entered an identical context, results of that time check
        and counting are ignored.
        """
        self.__entered_count += 1
        self.__nested_level += 1
        if self.__nested_level == 1:
            self.__started = _clock()

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Exit from this context."""
        if self.__nested_level == 1:
            self.__elapsed_time += _clock() - self.__started
            self.__checked_count += 1
        if exc_type:
            self.__raised_count += 1
        self.__nested_level -= 1

    def profile(self, func):
        """Decorate the below function as inside of this context."""
        def wrapper(*args, **kwargs):
            with self:
                return func(*args, **kwargs)
        return wrapper

if __name__ == "__main__":
    print("\n[ SimpleProfiler demo ] Profiles the Fibonacci function!\n")
    p = SimpleProfiler()

    @p.profile
    def fib(x):
        return x if x < 2 else fib(x - 1) + fib(x - 2)
    def fib_demo():
        p.reset()
        try:
            for n in range(40):
                p.reset()
                print(" profiling fib(%d) in progress..."
                        % n, end="", flush=True)
                print("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b=%d, %f seconds elapsed\n"
                      "   %d entered, %d checked, %d raised"
                        % (fib(n), p.elapsed_time, p.entered_count, \
                           p.checked_count, p.raised_count))
        except KeyboardInterrupt:
            print("\n***** aborted by user *****\n"
                  "   %f seconds elapsed (until abort)\n"
                  "   %d entered, %d checked, %d raised"
                    % (p.elapsed_time, p.entered_count, p.checked_count,
                       p.raised_count))
    print("[normal (uncached) version]")
    fib_demo()

    from functools import lru_cache
    @p.profile
    @lru_cache()
    def fib(x):
        return x if x < 2 else fib(x - 1) + fib(x - 2)
    print("\n[cached version]")
    fib_demo()

拍手[0回]

PR

GNU Toolchain for Hitachi H8/300 series for Windows

今更シリーズの第3!弾、さて今回は往年の組み込み用 CPU、日立 H8/300 用の GCC などは如何でしょうか。ルネサスさん、なんと一部品番については 2020 年代中頃辺りまで供給するつもりらしいです。
秋月でもまだまだ扱いがあるあたり、根強い需要があるのか、それとも余程在庫が残ってるのか…


妙な邪推はさておき、x86 な Windows で動作する最新(本稿執筆時)の H8/300 用ビルド済み

  • binutils 2.30 (LTO)
  • gcc 8.3.0 (C/C++, libstdc++, LTO, H8/300|H8S|H8SX multilib)
  • newlib 2.5.0 (H8/300|H8S|H8SX multilib)
  • gdb 8.2.1

を公開しておきます。
MSYS2 32bit 環境下でビルドしてありますが、利用に MSYS2 や他のライブラリの類のインストールは必要ありません。詳しくは同梱の readme.txt とかを見て下さい。


gcc-8.3.0_h8300-hitachi-elf_Windows.7z (SHA-1: 22a9f12535959354877ecac1e77fb94c3108653b)

  • 素の gcc 8.3.0 ではコード生成に問題がある(特に H8SX で newlib や libstdc++ ですらコンパイルに失敗する)のを修正済み
  • ついでに素の gcc 8.3.0 より少し良いコードを生成するよう修正
  • というか巷に散見される H8/300 用 GCC は 4.9 / 4.7 / 2.9 と古かったりするので…

同梱の Windows インストーラー(*.msi) を使えば直ちにインストールできます。確認とか全く聞いてこない手抜き仕様なので注意。
アンインストールも Windows インストーラーなので簡単。

拍手[1回]

玄箱(初代)に Debian Jessie を入れたらラジーパイZeroより狭くて遅かった件

もう平成も終わろうというのに、今さら玄箱(初代)に Debian Jessie (archive) を debootstrap して linux-4.4.229 を添えてみました。


想定する構成

  • 玄箱(初代)専用、玄箱/HG も対象外
  • ブートローダーはフラッシュ版 U-Boot (u-boot-1.2.0-hd.flash.bin) を使う
    入手先およびフラッシュ書き込み方法は割愛
  • HDD のパーティション、およびフォーマットは
    # /etc/fstab
    proc    /proc   proc    defaults        0       0
    /dev/sda3       /       ext4    defaults,noatime        0       1
    /dev/sda1       /boot   ext2    defaults,noatime        0       2
    /dev/sda2       swap    swap    defaults        0       0
    
    これは玄箱(初代)本来の割り方ではなく、他所の野良 linux 化でよくされていた割り方とも微妙に違うので、U-Boot 変数の設定とかを引き写してくる際には注意

カーネルとユーザーランド


初期設定で…

  • ホスト名は kuroboxHD
  • IPv4 (DHCP 自動設定)、IPv6、mDNS 応答 (kuroboxHD.local)、および ssh が有効
  • netconsole は無効
  • シリアルコンソール、または ssh 経由で root へログイン可能、パスワードは kuroboxHD
  • セルフカーネルコンパイル(要8時間以上)が可能な程度に色々と入れてあります、あと Python3 とかも
    まあ普通に Debian Jessie なんで好みで apt-get して下さい

拍手[0回]

GNU Toolchain for Renesas SH1, SH2, SH3 and SH4 for Windows

今更 SuperH かよ、とも思ったがルネサスさんまだ製品展開頑張ってるんですね…
(最大クロック増加・2ウェイスーパースケーラ化・割り込み応答速度向上など)

FA SBC にも結構使われているようで秋月にも SH2A 基板が出てくるあたり、それなりに力を入れているのかも。あと所用でその SH2A な FA SBC を評価することになったので、GCC ビルドすっか、というお話。


それで、以前の投稿ではここからビルド手順が書いてあったのですが、ややこしいのでばっさり割愛。x86 な Windows で動作する最新(本稿執筆時)の SuperH 用ビルド済み

  • binutils 2.30 (LTO)
  • gcc 8.3.0 (C/C++, libstdc++, LTO, SH1~4 multilib)
  • newlib 2.5.0 (SH1~4 multilib)
  • gdb 8.2.1

を公開しておきます。
MSYS2 32bit 環境下でビルドしてありますが、利用に MSYS2 や他のライブラリの類のインストールは必要ありません。詳しくは同梱の readme.txt とかを見て下さい。


gcc-8.3.0_sh-renesas-elf_Windows.7z (SHA-1: 985d36941f4a47708ce50985b4412958c4b7ec05)


同梱の Windows インストーラー(*.msi) を使えば直ちにインストールできます。確認とか全く聞いてこない手抜き仕様なので注意。
アンインストールも Windows インストーラーなので簡単。

拍手[0回]

にわかもすなるIoTといふものを(その5)

前回に引き続いてラジーパイねた。
その前回で結局ローカルのIPカメラ画像をインターネット越しライブ配信するやりかたを書かずじまいだったけど、そんなのは各自勝手にやってくれとしか(をい) と言うかもうRTMPで流れてるんだからRTMP受け付けてくれる動画配信サービスにFFmpegで投げればいいだけ。

お次にラジーパイにやらせるねたはずばり、貧乏人のハイレゾオーディオ。
個人的にオーディオ系の話題は宗教あるいは「沼」だと思ってたので敬して遠ざけておくのがいいやね、どうせ耳にLPFが勝手にインストールされるお年頃だし(笑)…とか考えてたら、
  • ラジーパイからはI2SとかいうD/Aコンバーター直結用インターフェース信号が出ている
  • そのI2Sにぶら下げたD/Aコンバーターをラジーパイからオーディオデバイスとして扱う用意(OS/ドライバ/ミドルウェア/アプリ)が既にある
  • ユニバーサル基板での手ハンダ電子工作レベルでI2S接続して実際に音を出せるD/AコンバーターICが秋葉原で安く売られている

今I2S DAC ICを求めて全力疾走している僕は自宅警備員をしているごく一般的な男の子。強いて違うところをあげるとすればついさっきハイレゾオーディオに興味を持ったってとこかナ…そんなわけで、外神田は千石電商本店1F奥のICコーナーにやってきたのだ。
TI / Burr-Brown 2Vrms DirectPath™, 112dB Audio Stereo DAC with 32-bit, 384kHz PCM Interface PCM5102A
『ウホッ!いいIC…』
(同じICを0.1"ピッチ変換基板に貼っただけのものが最近秋月でも扱いが始まったのでSSOPハンダ付けとかしたくない方はどうぞ。あとピッチ変換基板・ピンヘッダ込みでかつ安くあがるのでケチな人もw)

このIC、TI / Burr-Brown PCM5102Aの諸元はこんな感じ。
  • 2chステレオ、最大サンプルレート384kHz、32ビット分解能、SNR 112dB
  • 低歪FIR/低遅延IIRを随時切り替え可能な最大8倍補間デジタルフィルタ
    (アナログ段LPFがとても簡素に)
  • 負電源チャージポンプ内蔵でグランドセンター2.1Vrms ポップフリー・アナログライン出力
    (DC阻止コンデンサが不要でイヤホン規模負荷なら直接駆動可)
  • システムクロックはI2S BCKから内蔵PLLで自己供給可
    (I2Sソース同期したシステムクロック発振が不要に)
  • 秋葉パーツ屋での末端価格が円建てで3桁
    (価格破壊の風が語りかけます…安い、安すぎるw)

うん、一応TI / Burr-Brownって高級オーディオICの代名詞だと思ってたんですが…かがくのちからってすげー!
(動作設定用I2Cインターフェースや内蔵DSP動作をいじれる上位モデルもありますね…フフフ、奴はPCM5100番台の中でも最弱…)

基本的にはデータシートの"Typical Applications"に沿って作ればいい。必要なものは秋月で揃うので忘れずに買っておく。
実装上の留意点、というほどのものでもないが気をつけることとしては、
  • DAC ICとセラコンとの距離を最小化するべし。"Layout Guidelines"にもそう書いてある。デカップル用100nFは変換基板ピンヘッダ実装部の隙間に配置できる。チャージポンプ用セラコン2200nFも頑張れば変換基板上に配置できる(ヒント:裏側)
  • DAC ICのSCK、FMT、DEMPはDGNDに落とす(直結またはプルダウン)。ミュート制御用のXSMTは真面目に実装すると面倒なのでDVCCに上げておくに留める(直結またはプルアップ)。FLTはDGNDに落とすか、適当な手段でDVCCに上げられるようにしておくのもいい
  • 各I2S信号線にはリンギング防止に200Ω程度の終端抵抗を入れたほうがいいという意見もある(シュミットトリガ入力なのでそれほどの効果はないかも)

DAC ICのDEMPについてナニコレイミワカンナイ!な人が多いようなのでここで解説。
"Pin Functions"見ても "De-emphasis control for 44.1-kHz sampling rate" としか書かれていないからか頓珍漢な思い込みを書いてしまっている方もいるが、要は初期のCD-DAの一部に高域SNR改善のために予め高域を持ち上げて(Pre-emphasis)サンプリングしたものがあって、それを正しく再生するために逆特性フィルタを掛ける(De-emphasis)、そういうことである。
もちろん昔はアナログ段でそういう特性のフィルタを作っていたのだが、今や数百円のICに複数の32ビット積和演算器と数百語のレジスタが当たり前に入る世の中なので(笑)、デジタル補間処理のついでで片付いてしまう。ただ、Pre-emphasisかかってるCD-DAは希少で、最近ではまず使われない。DEMPピン制御するよりはFFmpegとかで24ビット変換しつつDe-emphasisしたほうがよいかと思われ。

PCM5102A on Raspberry PI 3 model B
その3に貼っていた写真をもう一度。こんな見てくれでもまあ立派に鳴ってくれるのはご愛敬。少なくともラジーパイ本体のPWMモジュールででっち上げた48kHz、12ビット分解能相当の音とは確実に違う。と言うかオーディオは凝りだすとホント沼なのでこのくらいで丁度いい。大体、たかが数千円のシングルボードコンピュータと数百円のDACに釣り合わない金銭と労力を投じても仕方がないよ(笑)

組み立てに失敗してなければRaspbianでもVolumioでもとりあえず同じICを採用しているHiFiBerry DACだと誤認させれば使えるはず。具体的な方法はGoogle先生に聞いて下さい。
食わず嫌いはいかんとな思って一応Volumioもちょっと使ってみたけど…どうも性に合わないようで。やっぱFFmpegとかでALSAデバイスとして扱うのが個人的には好きです(笑)

ああそうだ、一応官能評価も書いておくか。
  • LPFと耳鳴りの入った耳には48kHz以上のサンプルレートの違いは正直わからない。ただ16ビット分解能と24ビット分解能の違いはわかる
  • 低歪FIRフィルタ(FLT=DGND)は所謂ハイレゾオーディオ系、特にクラシックとかに向いている感じ。低遅延IIRフィルタ(FLT=DVCC)はJ-POPとか、あと不可逆圧縮されたソースに向いている感じ
    (なんか他の人の感想と逆なんだな…)
(個人の感想です、あくまでもw)

拍手[0回]

カレンダー

03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

フリーエリア

最新コメント

プロフィール

HN:
jjsuwa
性別:
非公開

バーコード

ブログ内検索

P R