目次: Zephyr
開発用のマシンではDebian Testingを使っているのですが、久しぶりにdist-upgradeしたところPython 3.8が消えてしまいました。Python 3.9に移行したみたいです。
アップデート時は「そうなんだ、3.9になったんだな。」くらいの認識でスルーしまいたが、Zephyrを使おうとしたら異変に気づきました。なんとZephyr SDKのGDBが動きません。どうしてこうなった。
$ riscv64-zephyr-elf-gdb riscv64-zephyr-elf-gdb: error while loading shared libraries: libpython3.8.so.1.0: cannot open shared object file: No such file or directory
Debianは元々Zephyr SDKのサポート範囲に入っていない(Ubuntuのみ)ですし、Debian Testingなんてサポートされるはずがないので、自力で解決する必要があります。
Zephyr SDKのビルド手順は簡単ですが、Debian Testingだとうまくいきません。
$ git clone https://github.com/zephyrproject-rtos/sdk-ng $ cd sdk-ng $ ./go.sh riscv64 ./go.sh: 行17: python: コマンドが見つかりません
Pythonが見つからず怒られます。Debian Testingは /usr/bin/pythonがなくなったため、go.shのpythonをpython3に書き換えてあげると動きます。他にもPython 3.8を想定している箇所があるので、Python 3.9に直します。
diff --git a/configs/riscv64.config b/configs/riscv64.config
index 295f2c0..a9fc301 100644
--- a/configs/riscv64.config
+++ b/configs/riscv64.config
@@ -46,5 +46,5 @@ CT_CC_LANG_CXX=y
CT_CC_GCC_LIBSTDCXX_NANO=y
CT_DEBUG_GDB=y
CT_GDB_V_9_2=y
-CT_GDB_CROSS_PYTHON_BINARY="python3.8"
+CT_GDB_CROSS_PYTHON_BINARY="python3.9"
CT_GDB_CROSS_BUILD_NO_PYTHON=y
diff --git a/go.sh b/go.sh
index e5442fa..7a45fd8 100755
--- a/go.sh
+++ b/go.sh
@@ -14,7 +14,7 @@ fi
COMMIT="d7da3a9c7f0f3a90bb4c71b91aea6cbc2471a541"
GITDIR=${PWD}
-JOBS=$(python -c 'import multiprocessing as mp; print(mp.cpu_count())')
+JOBS=$(python3 -c 'import multiprocessing as mp; print(mp.cpu_count())')
unameOut="$(uname -s)"
unameMachine="$(uname -m)"
SDKはbuild/output以下に生成されます。RISC-V 64であればbuild/output/riscv64-zephyr-elfです。生成されたバイナリが動くか確かめましょう。
$ cd build/output/riscv64-zephyr-elf/bin $ ./riscv64-zephyr-elf-gdb Segmentation fault
SEGVで死にました。うーん、だめそうですね……。次回以降、直せないかトライします。
目次: RISC-V
たまにRISC-V向けのQEMUの動きを見たいときがあって、デバッグビルドをするのですが、やり方を忘れがちなのでメモしておきます。
$ mkdir build $ cd build $ ../configure --target-list=riscv32-softmmu,riscv32-linux-user,riscv64-softmmu,riscv64-linux-user \ --disable-docs --enable-debug ... qemu 5.2.50 Install prefix: /usr/local BIOS directory: share/qemu firmware path: /usr/local/share/qemu-firmware binary directory: bin library directory: lib module directory: lib/qemu libexec directory: libexec include directory: include config directory: /usr/local/etc local state directory: /usr/local/var Manual directory: share/man Doc directory: /usr/local/share/doc ... thread sanitizer: NO rng-none: NO Linux keyring: YES FUSE exports: NO FUSE lseek: NO Subprojects libvhost-user: YES Found ninja-1.10.1 at /usr/bin/ninja $ ninja
ビルドが成功するとbuildディレクトリ以下にqemu-system-riscv32やqemu-system-riscv64が生成されているはずです。
目次: Zephyr
GDBとPython 3.9の組み合わせは、SEGVでクラッシュしました。調べてみると FedoraのBugzilla にドンピシャの情報が載っていました。Python 3.9とGDBの組み合わせが動かなかったこと、Red Hatの人がパッチを作ってくれて、5/28に修正されたこと、などが書いてあります。
Zephyr SDKのGDBは9.2(2020年5月23日リリース)で、上記のPython 3.9で動かすための修正は入っていません。残念。選択肢としては下記の2つが考えられます。
GDBのバージョンを変えると新たな厄災を招く恐れがあるため、今回は保守的に9.2 + パッチで行こうと思います。
Zephyr SDKは内部でCrosstool-NGというツールチェーンのビルドツールを利用しています。Zephyr SDKに突撃する前にCrosstool-NGの仕組みをおさらいし、9.2 + パッチでビルドする方法を試します。
Zephyr SDKのconfigs/ ディレクトリの下を見ると *.configファイルがたくさんあります。実はこれらはCrosstool-NGのコンフィグファイルです。このファイルをCrosstool-NGにコピーするとツールチェーンが作成できます。わかりやすいですね。
$ cd sdk-ng $ ls configs/ arc.config nios2.config xtensa_intel_byt_adsp.config arm.config riscv64.config xtensa_intel_s1000.config arm64.config sparc.config xtensa_nxp_imx8m_adsp.config i586.config x86_64-zephyr-elf.config xtensa_nxp_imx_adsp.config iamcu.config xtensa_intel_apl_adsp.config xtensa_sample_controller.config mips.config xtensa_intel_bdw_adsp.config
Crosstool-NGはツールチェーンの各モジュールにパッチを当てられます。例えばGDB 9.2ならばpackages/gdb/9.2/ の下にパッチファイルを置くと、若い番号から順番にパッチ適用してくれます。
$ ls packages/gdb/9.2/ 0000-musl_fix.patch 0004-allow-android.patch 0001-uclibc-no-gettimeofday-clobber.patch chksum 0002-xtensa-make-sure-ar_base-is-initialized.patch version.desc 0003-WIP-end-of-prologue-detection-hack.patch
このディレクトリに0005-xxxx.patchのような名前のパッチを追加すると、0004-allow-android.patchのあとにパッチを当ててくれます。便利ですね。パッチ当て処理の実装を見ましょう。
# crosstool-ng/scripts/functions
CT_DoExtractPatch()
{
...
CT_Pushd "${src_dir}/${basename}"
for d in "${patch_dirs[@]}"; do
CT_DoLog DEBUG "Looking for patches in '${d}'..."
if [ -n "${d}" -a -d "${d}" ]; then
for p in "${d}"/*.patch; do #★パッチファイルを列挙、パッチ当てる
if [ -f "${p}" ]; then
CT_DoExecLog ALL ${patch} --no-backup-if-mismatch -g0 -F1 -p1 -f -i "${p}"
fi
done
fi
done
...
ビルド後にできるログbuild.logをLooking for patchesで検索していくと、パッチを当てている箇所が確認できます。
... [DEBUG] Looking for patches in 'crosstool-ng/packages/gdb/9.2'... [DEBUG] ==> Executing: '/usr/bin/patch' '--no-backup-if-mismatch' '-g0' '-F1' '-p1' '-f' '-i' 'crosstool-ng/packages/gdb/9.2/0000-musl_fix.patch' [ALL ] patching file gdb/linux-nat.c [ALL ] patching file gdb/stopcode.h [DEBUG] ==> Return status 0 [DEBUG] ==> Executing: '/usr/bin/patch' '--no-backup-if-mismatch' '-g0' '-F1' '-p1' '-f' '-i' 'crosstool-ng/packages/gdb/9.2/0001-uclibc-no-gettimeofday-clobber.patch' [ALL ] patching file gnulib/configure [ALL ] patching file gnulib/import/m4/gettimeofday.m4 [DEBUG] ==> Return status 0 ...
Crosstool-NGがパッチを当てる順はシェルのファイル列挙順のため、ファイル名は必ずしも数字で始める必要はないです。しかし、前例に習ったほうが良いでしょう。パッチを0005-fix-python3.9.patchという名前で追加します。
$ git clone https://github.com/crosstool-ng/crosstool-ng $ cd crosstool-ng $ cat > packages/gdb/9.2/0005-fix-python3.9.patch (パッチをコピペする) $ ./bootstrap $ ./configure --enable-local $ make $ cp ../sdk-ng/configs/riscv64.config ./.config $ ./ct-ng menuconfig $ ./ct-ng build
ビルド後にできるログbuild.logを確認して、パッチが当たっていることを確かめます。
... [DEBUG] Looking for patches in 'crosstool-ng/packages/gdb/9.2'... [DEBUG] ==> Executing: '/usr/bin/patch' '--no-backup-if-mismatch' '-g0' '-F1' '-p1' '-f' '-i' 'crosstool-ng/packages/gdb/9.2/0000-musl_fix.patch' [ALL ] patching file gdb/linux-nat.c [ALL ] patching file gdb/stopcode.h [DEBUG] ==> Return status 0 [DEBUG] ==> Executing: '/usr/bin/patch' '--no-backup-if-mismatch' '-g0' '-F1' '-p1' '-f' '-i' 'crosstool-ng/packages/gdb/9.2/0001-uclibc-no-gettimeofday-clobber.patch' [ALL ] patching file gnulib/configure [ALL ] patching file gnulib/import/m4/gettimeofday.m4 [DEBUG] ==> Return status 0 ... [DEBUG] ==> Executing: '/usr/bin/patch' '--no-backup-if-mismatch' '-g0' '-F1' '-p1' '-f' '-i' 'crosstool-ng/packages/gdb/9.2/0005-python3.9.patch' [ALL ] patching file gdb/python/python.c [ALL ] Hunk #1 succeeded at 234 (offset -4 lines). [ALL ] Hunk #2 succeeded at 271 (offset -4 lines). [ALL ] Hunk #3 succeeded at 952 (offset -19 lines). [ALL ] Hunk #4 succeeded at 1552 (offset -68 lines). [ALL ] Hunk #5 succeeded at 1720 (offset -70 lines). [ALL ] patch unexpectedly ends in middle of line [DEBUG] ==> Return status 0
GDBの開発メールアーカイブから適当にコピペしてパッチを作ったので、Hunkがずれてるよって怒られましたが、パッチ当ては成功しています。あまり気にしなくても良いでしょう。ビルド後は動作確認しましょう。
$ cd ~/x-tools/riscv64-zephyr-elf/bin $ ./riscv64-zephyr-elf-gdb --version GNU gdb (crosstool-NG 1.24.0.254_fcf3233) 9.2 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
動きました。良かった良かった。
目次: Zephyr
前回はツールチェーンビルドの仕組みを確認するためCrosstool-NGに立ち返り、正常動作するバイナリが作成できましたが、手順が多くて面倒でした。実はZephyr SDKだけでパッチを当てる仕組みがあります。
Crosstool-NGのパッチ当ては前回紹介したpackagesの下にあるパッチを使うのが基本ですが、他の場所(ローカルパッチディレクトリ)も追加できます。CT_LOCAL_PATCH_DIRというコンフィグに設定されます。
$ ./ct-ng menuconfig Paths and misc options ---> () Local patch directory
Crosstool-NGのパッチ当て処理を見るとパッチを当てる順番を選択できるようになっています。
# crosstool-ng/scripts/functions
CT_DoExtractPatch()
{
...
CT_DoLog EXTRA "Patching ${basename}"
CT_DoExecLog ALL touch "${src_dir}/.${basename}.patching"
bundled_patch_dir="${CT_LIB_DIR}/packages/${pkg_dir}"
bundled_common_patch_dir="${CT_LIB_DIR}/packages/${pkg_name}"
local_patch_dir="${CT_LOCAL_PATCH_DIR}/${pkg_dir}" #★★ローカルパッチディレクトリ
#★ディレクトリ名を列挙
#★patch_orderは "bundled, local" になっていた、CT_PATCH_ORDERで決まるようだ
case "${patch_order}" in
bundled) patch_dirs=("${bundled_patch_dir}" "${bundled_common_patch_dir}");;
local) patch_dirs=("${local_patch_dir}");;
bundled,local) patch_dirs=("${bundled_patch_dir}" "${bundled_common_patch_dir}" "${local_patch_dir}");;
local,bundled) patch_dirs=("${local_patch_dir}" "${bundled_patch_dir}" "${bundled_common_patch_dir}");;
none) patch_dirs=;;
esac
CT_Pushd "${src_dir}/${basename}"
for d in "${patch_dirs[@]}"; do #★ディレクトリを順に辿る
CT_DoLog DEBUG "Looking for patches in '${d}'..."
if [ -n "${d}" -a -d "${d}" ]; then
for p in "${d}"/*.patch; do
if [ -f "${p}" ]; then
CT_DoExecLog ALL ${patch} --no-backup-if-mismatch -g0 -F1 -p1 -f -i "${p}"
fi
done
fi
done
...
今回のケースではpatch_orderは "bundled, local" になっていたので、packages -> ローカルパッチの順にパッチを当てるようです。patch_orderの決め方は深追いしていませんが、CT_PATCH_ORDERで決まるようです。
Zephyr SDKの設定ファイルを見るとローカルパッチディレクトリは下記のようになっています。
# configs/riscv64.config ... CT_LOCAL_PATCH_DIR="${CT_TOP_DIR}/../../patches"
CT_TOP_DIRとは何でしょう?ビルドログを追うとCT_TOP_DIR=/.../sdk-ng/build/build_riscv64でした。すなわちsdk-ng/patchesがローカルパッチディレクトリです。ディレクトリには既に6つほどのパッチが置かれています。
$ ls patches/gdb/9.2 0001-gdb-remote-make-tid-pid-type-long-in-write_ptid.patch 0002-gdb-Add-fixes-for-stdint-and-remote-debug-on-xtensa.patch 0003-gdb-xtensa-don-t-error-out-when-registers-cannot-be-.patch 0004-gdb-xtensa-use-remote-target-register-numer.patch 0005-gdb-arch-to-tell-whether-it-supports-g-packets.patch 0006-gdb-xtensa-support-disabling-use-of-g-packet.patch
ここにPython 3.9で落ちる問題を修正するパッチを追加します。
$ cd sdk-ng $ cat > patches/gdb/9.2/0007-gdb-fix-python3.9.patch (パッチをコピペする) $ ./go.sh riscv64
ビルドログはbuild/build_riscv64/build.logに作られます。
# Crosstool-NGの持っているパッチを当てているログ [DEBUG] Looking for patches in 'sdk-ng/share/crosstool-ng/packages/gdb/9.2'... [DEBUG] ==> Executing: '/usr/bin/patch' '--no-backup-if-mismatch' '-g0' '-F1' '-p1' '-f' '-i' 'sdk-ng/share/crosstool-ng/packages/gdb/9.2/0000-musl_fix.patch' [ALL ] patching file gdb/linux-nat.c [ALL ] patching file gdb/stopcode.h [DEBUG] ==> Return status 0 ... # Zephyr SDKのローカルパッチを当てているログ [DEBUG] Looking for patches in 'sdk-ng/share/crosstool-ng/packages/gdb'... [DEBUG] Looking for patches in 'sdk-ng/build/build_riscv64/../../patches/gdb/9.2'... [DEBUG] ==> Executing: '/usr/bin/patch' '--no-backup-if-mismatch' '-g0' '-F1' '-p1' '-f' '-i' 'sdk-ng/build/build_riscv64/../../patches/gdb/9.2/0001-gdb-remote-make-tid-pid-type-long-in-write_ptid.patch' [ALL ] patching file gdb/remote.c [DEBUG] ==> Return status 0 ... # 追加したパッチを当てているログ [DEBUG] ==> Executing: '/usr/bin/patch' '--no-backup-if-mismatch' '-g0' '-F1' '-p1' '-f' '-i' 'sdk-ng/build/build_riscv64/../../patches/gdb/9.2/0007-gdb-fix-python3.9.patch' [ALL ] patching file gdb/python/python.c [ALL ] Hunk #1 succeeded at 234 (offset -4 lines). [ALL ] Hunk #2 succeeded at 271 (offset -4 lines). [ALL ] Hunk #3 succeeded at 952 (offset -19 lines). [ALL ] Hunk #4 succeeded at 1552 (offset -68 lines). [ALL ] Hunk #5 succeeded at 1720 (offset -70 lines). [ALL ] patch unexpectedly ends in middle of line [DEBUG] ==> Return status 0
ちなみにZephyr SDKのビルド後、GDBのソースコードはsdk-ng/build/build_riscv64/.build/riscv64-zephyr-elf/src/gdbに展開されます。パッチが正常に当たったか確認するなら、このソースコードを見れば確実でしょう。
SDKはbuild/output以下に生成されます。RISC-V 64であればbuild/output/riscv64-zephyr-elfです。生成されたバイナリが動くか確かめましょう。
$ cd build/output/riscv64-zephyr-elf/bin $ ./riscv64-zephyr-elf-gdb --version GNU gdb (crosstool-NG 1.24.0.212_d7da3a9) 9.2 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
動きました、良かった良かった。build/output下に生成されたriscv64-zephyr-elfディレクトリをZephyr SDKのインストールディレクトリ下にある同名のディレクトリと差し替えれば、GDBが動くはずです。
年末(2020年12月20日の日記参照)に、1月はSUPER VALUE 21 Jより安いチケットがVALUE 3で出ると予想しましたが、外れましたね。1/30の羽田→札幌便を見ると、最安はVALUE 3 Jで年末からほとんど変わっていません。
いやまあ、SUPER VALUE 21とVALUE 3の値段がほとんど変わらない時点で、かなり異常事態なんですけど……。
なんと全25便中、半分近い11便が欠航しています。飛ばす回数を自体を減らし、客単価の維持とおそらく各便ごとの黒字を確保しているのでしょう。単発で黒字が出たとしても、確実に収益にはダメージがありますよね。安いイメージが付いてしまうより良いのかなあ?
燃料費などは減便で節約できても、飛行機はリースなので飛んでも飛ばなくてもお金が掛かります。飛ばせるならいくらでも飛ばしたいでしょう。
早いところCOVID-19には収束してもらって、気軽に旅行や帰省できる日が来てほしいですね。ANAは今かなり苦しいでしょうけど、日本の翼を担う会社として何とか踏みとどまってほしいところ……。
久しぶりにPlayStation Vitaを起動したところ、ネットワークに繋げる系アプリがほぼ全滅していました。
プラットフォーム依存のゲーム機は、本体が元気でもサードパーティの撤退やサービス終了に伴って、勝手にポンコツになってしまい悲しいです。結構高かったのに……。
ソニー製
サードパーティ製
PlayStation Storeを見ると「アプリケーション」はたった14個、サードパーティ製のアプリは1つ(ROBOTICS; NOTES ELITE AR)だけです。PS Vitaは既に9年経過(2011年12月発売)しており、ぶっちゃけソニーすらもVitaを見放している節があり、もう完全にオワコンです。
それなりに大きなプラットフォームの終焉を間近で見たのは貴重な体験、とはいえ、買った人は何も嬉しくないよね……。
メモ: 技術系?の話はFacebookから転記しておくことにした。多少修正。
Zoomって、バージョンアップのお知らせを全くしてこないので、起動時に勝手にアップデートされていると思っていたんですが、全くそんなことはなかったですね。ずっと古いバージョンの5.3.1(2020/09/28リリース)のまま使っていました。
手動でアップデートしたところ、無事に最新版の5.4.9になりました。4ヶ月で大分数字が変わりましたね。
比較的新しいアプリの割にアップデートは保守的ですね?不思議な設計だな……??
Facebookのコメントで「ミーティングの後」にバージョンアップのお知らせが出ることを教えてもらいました。
ミーティング前にバージョンアップすると遅刻する可能性大なので、ミーティング終了後に表示するのは良いアイデアですね。でも残念ながら、見たことないんだよな……。うちのZoomは何か変なんだろうか??
メモ: 技術系?の話はFacebookから転記しておくことにした。加筆。
目次: Zephyr
Zephyrでリセットできないんだけど、って言われて調べたので、忘れないうちに記録に残しておきます。
RISC-Vの規格ではリセット処理について何も記述されていませんので、リセット処理はハードウェア依存となります。QEMUのRISC-V virtマシンはどうかというと、SiFiveのナイスガイ達が作ってくれたリセットの仕組みがあります。
// qemu/hw/riscv/virt.c
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
} virt_memmap[] = {
[VIRT_DEBUG] = { 0x0, 0x100 },
[VIRT_MROM] = { 0x1000, 0xf000 },
[VIRT_TEST] = { 0x100000, 0x1000 }, //★アドレス0x00100000にある★
[VIRT_RTC] = { 0x101000, 0x1000 },
...
// qemu/hw/riscv/virt.c
static void virt_machine_init(MachineState *machine)
{
...
/* SiFive Test MMIO device */
sifive_test_create(memmap[VIRT_TEST].base); //★テストデバイスを追加している★
// qemu/hw/misc/sifive_test.c
/*
* Create Test device.
*/
DeviceState *sifive_test_create(hwaddr addr)
{
DeviceState *dev = qdev_new(TYPE_SIFIVE_TEST);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
return dev;
}
...
static void sifive_test_write(void *opaque, hwaddr addr,
uint64_t val64, unsigned int size)
{
if (addr == 0) {
int status = val64 & 0xffff;
int code = (val64 >> 16) & 0xffff;
switch (status) {
case FINISHER_FAIL:
exit(code);
case FINISHER_PASS:
exit(0);
case FINISHER_RESET:
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); //★ここに到達するとリセットが掛かるはず★
return;
default:
break;
}
}
qemu_log_mask(LOG_GUEST_ERROR, "%s: write: addr=0x%x val=0x%016" PRIx64 "\n",
__func__, (int)addr, val64);
}
// qemu/include/hw/misc/sifive_test.h
enum {
FINISHER_FAIL = 0x3333,
FINISHER_PASS = 0x5555,
FINISHER_RESET = 0x7777 //★この値を書けば良さそう★
};
つまり0x100000に0x00007777を4バイトWriteすれば良さそうです。
Zephyrのサンプルshellを使います。理由はリブートするコマンドが簡単に使えるからです。CONFIG_REBOOTを有効にする必要があります。またshellは起動後プロンプトが出るだけで、リセットが掛かったかどうかわかりにくいため、起動時のバナーも有効にしておくと良いです。
CONFIG_REBOOT=y Boot Options ---> [ ] Reboot functionality CONFIG_BOOT_BANNER=y General Kernel Options ---> Kernel Debugging and Metrics ---> [ ] Boot banner
ちょっと長いので一旦切ります。次回は実装と動作確認をします。
目次: Zephyr
Zephyrにはリブートを行う関数sys_reboot() が既に実装されており、アーキテクチャごとのリブート用関数sys_arch_reboot() を呼ぶ仕組みです。
// zephyr/subsys/power/reboot.c
void sys_reboot(int type)
{
(void)irq_lock();
#ifdef CONFIG_SYS_CLOCK_EXISTS
sys_clock_disable();
#endif
sys_arch_reboot(type); //★★アーキテクチャごとのリブート関数を呼ぶ
/* should never get here */
printk("Failed to reboot: spinning endlessly...\n");
for (;;) {
k_cpu_idle();
}
}
// zephyr/soc/riscv/riscv-privilege/virt/soc.c
/* Reboot machine */
#define FINISHER_REBOOT 0x7777
void sys_arch_reboot(int type)
{
volatile uint32_t *reg = (uint32_t *)SIFIVE_SYSCON_TEST;
*reg = FINISHER_REBOOT; //★★0x100000に0x00007777をWrite
ARG_UNUSED(type);
}
// zephyr/soc/riscv/riscv-privilege/virt/soc.h
#include <soc_common.h>
#include <devicetree.h>
#define SIFIVE_SYSCON_TEST 0x00100000 //★追加
#define RISCV_MTIME_BASE 0x0200BFF8
#define RISCV_MTIMECMP_BASE 0x02004000
実装は素直にsys_arch_reboot() を追加しただけです。そんなに難しくないですよね。
前回説明した通り、サンプルアプリのshellを使って動作確認します。
$ cmake -G Ninja -DBOARD=qemu_riscv32 ../samples/subsys/shell/shell_module/ $ ninja menuconfig ★★CONFIG_REBOOTとCONFIG_BOOT_BANNERを有効にする $ ninja run [0/1] To exit from QEMU enter: 'CTRL+a, x'[QEMU] CPU: riscv32 *** Booting Zephyr OS build v2.5.0-rc1-276-ge7d3bb714bc2 *** uart:~$ kernel reboot cold ★★↑ここでリブートされる *** Booting Zephyr OS build v2.5.0-rc1-276-ge7d3bb714bc2 *** uart:~$
無事リブートしました。本当にリブートしてるのか不安になるくらい速いです。Zephyrは起動時に何も言わないので、Linuxと比べるとリブートは簡素に見えますね。速いのは良いんだけど、感動がちょっと薄いのが難点かも?
目次: ベンチマーク
昔(2017年6月14日の日記参照)yesの速度を測ったりして遊んでいましたが、改めてRyzen 7 2700でyes | pv > /dev/nullを実行してみたところ、出力速度が不安定です。
出力速度が不安定なときに、topで各CPUスレッドの負荷を眺めていると、ときどきプロセスが違うCPUスレッドに移動しているようにみえます。コアごとに動作周波数が違うせいか、yesのプロセスが別のコアに移ったとき、移動先のコアが省エネモードから最高周波数に立ち上がるまでのラグが影響しているんでしょうか?どうやって確かめましょうね?特定のスレッドに貼り付けたらエエんかしら??
てなことを最初考えたんですが、実はそんなに難しい話ではなく、単にyesとpvが同じコアに割り付けられたときに、速度的に不利に働いているだけのような気がしてきました。実験するためtasksetを使って適当にスレッドを散らします。
かなり性能が変わります。コアが同じかどうか?はもちろん重要ですが、Zenアーキテクチャはコアコンプレックスの内か外かで性能に大きな違いが出ます。結果が安定しなかったのはプロセスがコアコンプレックス外に行ったり来たりしていたためでしょうね。
Debian TestingのLinux Kernel(現状、5.10.4-1)は、コアコンプレックスまでは考慮してくれないらしく、コアコンプレックス内と外のコアのどちらで実行しても良いよ、という設定にすると、処理が遅くなる方に割り付けてしまいます。
$ taskset 0x110 yes | taskset 0x1 pv > /dev/null [4.59GiB/s] $ top top - 02:05:53 up 16 days, 9:39, 20 users, load average: 0.64, 0.96, 1.06 Tasks: 355 total, 3 running, 349 sleeping, 2 stopped, 1 zombie %Cpu0 : 7.5 us, 75.8 sy, 0.0 ni, 16.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st ★pvはCPU 0で動作する %Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu2 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu3 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu4 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu5 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu6 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu7 : 0.3 us, 0.0 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu8 : 6.0 us, 79.1 sy, 0.0 ni, 14.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st ★yesはCPU 4のほうが速いはずだが、CPU 8で動作する %Cpu9 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu10 : 0.7 us, 0.0 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu11 : 0.3 us, 0.0 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu12 : 0.3 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu13 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu14 : 0.7 us, 0.3 sy, 0.0 ni, 99.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st %Cpu15 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 32106.7 total, 582.9 free, 3532.5 used, 27991.3 buff/cache MiB Swap: 0.0 total, 0.0 free, 0.0 used. 27906.8 avail Mem
パッと見、法則性が良くわかりませんでした。なるべくビジーなスレッドから遠い番号のCPUスレッドに割り当てようとする?のかもしれませんね。
(※1)Ryzen 7は1コア2スレッドなので、スレッド (0, 1), (2, 3), (4, 5) のように2スレッドが同じコアで実行されます。
メモ: 技術系?の話はFacebookから転記しておくことにした。後半を加筆。
< | 2021 | > | ||||
<< | < | 01 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | - | 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 |
31 | - | - | - | - | - | - |
合計:
本日: