2021年 2月 2日

Zephyr と QEMU のリセット その 1 - 準備編

目次: Zephyr を調べる - まとめリンク

Zephyr でリセットできないんだけど、って言われて調べたので、忘れないうちに記録に残しておきます。

RISC-V の規格ではリセット処理について何も記述されていませんので、リセット処理はハードウェア依存となります。QEMU の RISC-V virt マシンはどうかというと、SiFive のナイスガイ達が作ってくれたリセットの仕組みがあります。

QEMU RISC-V virt マシンのリセット処理

// 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 は起動後プロンプトが出るだけで、リセットが掛かったかどうかわかりにくいため、起動時のバナーも有効にしておくと良いです。

REBOOT, BOOT_BANNER を有効にする
CONFIG_REBOOT=y

  Boot Options  --->
    [ ] Reboot functionality

CONFIG_BOOT_BANNER=y

  General Kernel Options  --->
    Kernel Debugging and Metrics  --->
      [ ] Boot banner

ちょっと長いので一旦切ります。次回は実装と動作確認をします。

編集者: すずき(更新: 2021年 2月 6日 01:03)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 3日

Zephyr と QEMU のリセット その 2 - 実装編

目次: Zephyr を調べる - まとめリンク

Zephyr にはリブートを行う関数 sys_reboot() が既に実装されており、アーキテクチャごとのリブート用関数 sys_arch_reboot() を呼ぶ仕組みです。

QEMU RISC-V virt マシンのリブート処理を実装

// 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 と比べるとリブートは簡素に見えますね。速いのは良いんだけど、感動がちょっと薄いのが難点かも?

編集者: すずき(更新: 2021年 2月 6日 01:04)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 4日

不安定な yes

昔(2017年 6月 14日の日記参照)yes の速度を測ったりして遊んでいましたが、改めて Ryzen 7 2700 で yes | pv > /dev/null を実行してみたところ、出力速度が不安定です。

GNU yes 8.32 を単独で実行
[6.73GiB/s](不安定)
GNU yes 8.32 と、隣で while :; do :; done を実行
[6.98GiB/s](若干安定)

出力速度が不安定なときに、top で各 CPU スレッドの負荷を眺めていると、ときどきプロセスが違う CPU スレッドに移動しているようにみえます。コアごとに動作周波数が違うせいか、yes のプロセスが別のコアに移ったとき、移動先のコアが省エネモードから最高周波数に立ち上がるまでのラグが影響しているんでしょうか?どうやって確かめましょうね?特定のスレッドに貼り付けたらエエんかしら??

てなことを最初考えたんですが、実はそんなに難しい話ではなく、単に yes と pv が同じコアに割り付けられたときに、速度的に不利に働いているだけのような気がしてきました。実験するため taskset を使って適当にスレッドを散らします。

隣のスレッド(= 同じコア)
$ taskset 0x2 yes | taskset 0x1 pv > /dev/null
[6.34GiB/s]
2つ隣のスレッド(= 違うコア、コアコンプレックス内)
$ taskset 0x4 yes | taskset 0x1 pv > /dev/null
[7.34GiB/s]
4つ隣のスレッド(= 違うコア、コアコンプレックス内)
$ taskset 0x10 yes | taskset 0x1 pv > /dev/null
[7.20GiB/s]
8つ隣のスレッド(= 違うコア、コアコンプレックス外)
$ taskset 0x100 yes | taskset 0x1 pv > /dev/null
[4.65GiB/s]
12つ隣のスレッド(= 違うコア、コアコンプレックス外)
$ taskset 0x1000 yes | taskset 0x1 pv > /dev/null
[4.66GiB/s]

かなり性能が変わります。コアが同じかどうか?はもちろん重要ですが、Zen アーキテクチャはコアコンプレックスの内か外かで性能に大きな違いが出ます。結果が安定しなかったのはプロセスがコアコンプレックス外に行ったり来たりしていたためでしょうね。

Debian Testing の Linux Kernel(現状、5.10.4-1)は、コアコンプレックスまでは考慮してくれないらしく、コアコンプレックス内と外のコアのどちらで実行しても良いよ、という設定にすると、処理が遅くなる方に割り付けてしまいます。

実行中の top の様子
$ 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年 2月 4日 02:15)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 5日

デノーマルフラッシュ

浮動小数点数の演算では IEEE 754 という規格があり、x86 系のプロセッサはこの規格に基づいた演算を行っています。規格のなかに非正規化数(Denormal Number もしくは Subnormal Number とも)という、極めて小さい特殊な数のカテゴリがあります(参考: IEEE 754 - Wikipedia)。

通常は Denormal 数も正確に演算しますが、Denormal 数の演算は遅いです。計算精度より計算速度が重要な場面では MXCSR レジスタに特殊なフラグを設定することで、Denormal 数の扱いを変更し、高速に演算することができます(参考: FTZ フラグと DAZ フラグの設定 - インテル C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス)。

基本的には Denormal 数を無視して 0 として扱うようにしますが、Intel のプロセッサでは入力側と出力側を別々に扱えるようです。設定可能なフラグは 2つあります。デノーマルフラッシュって必殺技の名前っぽいよね。どうでもいいけど。

FTZ (Flush To Zero)
演算結果が Denormal 数だった場合、ゼロとして扱う。
有効にする方法 _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON)
DAZ (Denormals Are Zeros)
入力が Denormal 数だった場合、ゼロとして扱う。
有効にする方法 _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON)

うーん。わかるような、わからないような。こういうときは実際に動かしてどんな結果になるか試すのが一番良いでしょう。FTZ と DAZ を有効にする方法は Intel コンパイラの説明から抜粋したものですが、GCC でも全く同じ方法で利用可能です。

Denormal Flush の実験プログラム

#include <stdint.h>
#include <stdio.h>
#include <pmmintrin.h>

double zero = 0.0f;

union {
	double f;
	long long n;
} a, b, c, d, ab, ac, ca, dc;

void test()
{
	a.n = 0x0008000000000000ULL;
	b.n = 0x0004000000000000ULL;
	c.n = 0x0010000000000000ULL;
	d.n = 0x0014000000000000ULL;
	ab.f = a.f + b.f;
	ac.f = a.f + c.f;
	ca.f = c.f - a.f;
	dc.f = d.f - c.f;

	printf("  a   : %e(0x%08llx)\n"
		"  b   : %e(0x%08llx)\n"
		"  c   : %e(0x%08llx)\n"
		"  d   : %e(0x%08llx)\n"
		"  a+b : %e(0x%08llx)\n"
		"  a+c : %e(0x%08llx)\n"
		"  c-a : %e(0x%08llx)\n"
		"  d-c : %e(0x%08llx)\n"
		"  a==0: %d\n\n",
		a.f, a.n, b.f, b.n, c.f, c.n, d.f, d.n,
		ab.f, ab.n, ac.f, ac.n, ca.f, ca.n, dc.f, dc.n,
		a.f == zero);
}

int main(int argc, char *argv[])
{
	_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_OFF);
	_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_OFF);
	printf("FTZ:OFF, DAZ:OFF\n");
	test();

	_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_OFF);
	_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
	printf("FTZ:OFF, DAZ:ON\n");
	test();

	_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
	_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_OFF);
	printf("FTZ:ON, DAZ:OFF\n");
	test();

	_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
	_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
	printf("FTZ:ON, DAZ:ON\n");
	test();

	return 0;
}

変数 a と b は Denormal 数です(double の exponent 部分が 0)。変数 c は非常に小さいですが通常の数です。最後の a.f == zero は Denormal 数と 0 を比較したときに、等しければ 1、等しくなければ 0 が出力されます。実行結果とともに説明したほうが良いと思うので、実行結果を示します。

Denormal Flush の動作確認
$ gcc a.c && ./a.out

FTZ:OFF, DAZ:OFF
  a   : 1.112537e-308(0x8000000000000)
  b   : 5.562685e-309(0x4000000000000)
  c   : 2.225074e-308(0x10000000000000)
  d   : 2.781342e-308(0x14000000000000)
  a+b : 1.668805e-308(0xc000000000000)  ★Denorm1 + Denorm2 = Denorm3
  a+c : 3.337611e-308(0x18000000000000) ★Denorm1 + Normal1 = Normal1+α
  c-a : 1.112537e-308(0x8000000000000)  ★Normal1 - Denorm1 = Denorm4
  d-c : 5.562685e-309(0x4000000000000)  ★Normal2 - Normal1 = Denorm5
  a==0: 0                               ★Denorm1 == 0      ? いいえ

FTZ:OFF, DAZ:ON
  a   : 1.112537e-308(0x8000000000000)
  b   : 5.562685e-309(0x4000000000000)
  c   : 2.225074e-308(0x10000000000000)
  d   : 2.781342e-308(0x14000000000000)
  a+b : 0.000000e+00(0x00000000)        ★Denorm1 + Denorm2 = 0(※1)
  a+c : 2.225074e-308(0x10000000000000) ★Denorm1 + Normal1 = Normal1 → 入力の Denormal が 0 扱い = DAZ
  c-a : 2.225074e-308(0x10000000000000) ★Normal1 - Denorm1 = Normal1 → 入力の Denormal が 0 扱い = DAZ
  d-c : 5.562685e-309(0x4000000000000)  ★Normal2 - Normal1 = Denorm5
  a==0: 1                               ★Denorm1 == 0      ? はい → 入力の Denormal が 0 扱い = DAZ

FTZ:ON, DAZ:OFF
  a   : 1.112537e-308(0x8000000000000)
  b   : 5.562685e-309(0x4000000000000)
  c   : 2.225074e-308(0x10000000000000)
  d   : 2.781342e-308(0x14000000000000)
  a+b : 0.000000e+00(0x00000000)        ★Denorm1 + Denorm2 = 0(※1)
  a+c : 3.337611e-308(0x18000000000000) ★Denorm1 + Normal1 = Normal1+α
  c-a : 0.000000e+00(0x00000000)        ★Normal1 - Denorm1 = 0 → 演算結果の Denormal が 0 扱い = FTZ
  d-c : 0.000000e+00(0x00000000)        ★Normal2 - Normal1 = 0 → 演算結果の Denormal が 0 扱い = FTZ
  a==0: 0                               ★Denorm1 == 0      ? いいえ

FTZ:ON, DAZ:ON
  a   : 1.112537e-308(0x8000000000000)
  b   : 5.562685e-309(0x4000000000000)
  c   : 2.225074e-308(0x10000000000000)
  d   : 2.781342e-308(0x14000000000000)
  a+b : 0.000000e+00(0x00000000)        ★Denorm1 + Denorm2 = 0(※1)
  a+c : 2.225074e-308(0x10000000000000) ★Denorm1 + Normal1 = Normal1 → 入力の Denormal が 0 扱い = DAZ
  c-a : 2.225074e-308(0x10000000000000) ★Normal1 - Denorm1 = Normal1 → 入力の Denormal が 0 扱い = DAZ
  d-c : 0.000000e+00(0x00000000)        ★Normal2 - Normal1 = 0   → 演算結果の Denormal が 0 扱い = FTZ
  a==0: 1                               ★Denorm1 == 0      ? はい → 入力の Denormal が 0 扱い = DAZ

(※1)演算結果だけでは、入力の Denormal 数が両方 0 扱いなのか、結果の Denormal 数が 0 扱いなのか、判別できない。

FTZ と DAZ が発生する例を示したつもりです。できるだけ頑張って説明してみたんですが、良くわからなかったらごめんなさい。

編集者: すずき(更新: 2021年 2月 6日 03:08)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 6日

レガシィの半年点検

ディーラーから電話がかかってきて「(車検と一緒にセットで頼んだ)半年点検どうしましょうか?」と聞かれました。実は頼んだことを忘れていたので、確認してもらって助かりました。「半年前の車検で一緒にご依頼されました半年点検なんですが〜」と説明が妙に手慣れた感じだったところを見るに、頼んでおいて忘れてしまう、私みたいな人が多いんだな〜なんて思った。

点検結果はというと、走行系の異常はありませんでした。フロントのウォッシャー液を送るゴムホースが破損していて、フロントのウォッシャー液が出ないうえ、むりやり使ったらエンジンルームにダダ漏れするそうです。え、そうなの??全く気づいていませんでした。ウォッシャー液って全然使わないんだよね……。

部品の取り寄せが要るためすぐには直せず、修理の際はご予約いただきたい、とのことだったので、またどこかの土曜日にでも持っていこうと思います。

スバルのセダンは 1つだけ

私のようなおじさんがディーラーに行くと、新車のカタログをたくさん渡されて「新車どうです?」って話されるんですが、最近のスバルではなーんにも聞かれません。今のスバルはレガシィ B4 GT の乗り換え先がないからです。

スバルの現行車種でセダンはインプレッサ G4 だけです。G4 は上級グレードの 2.0i でも、2リッター NA(154馬力)です。レガシィ B4 GT の 2リッターターボ(280馬力)から乗り換えると大幅パワーダウンは否めず、おすすめしづらいのでしょう。現にディーラーでもカタログだけもらったものの、ほとんどプッシュされませんでした。

ちょっと前なら、インプレッサ WRX S4 STI Sport がありましたが、生産終了してしまいました。仮に現行車種だったとしても、一般人向けとは思えんし、気軽に「WRX S4 いかがですか?」とは言いにくいでしょう。スバルのディーラーにとってセダン乗りは鬼門ですね。

編集者: すずき(更新: 2021年 2月 13日 02:56)

コメント一覧

  • hdk 
    トヨタのディーラーではときどき聞かれます。まぁハッチバックコンパクトカーというジャンルなので確かに車種は豊富なんですが、4人乗り全長3000mmの新車は他社を含めてももう1台もないのに... 
    (2021年02月13日 08:17:11)
  • すずき 
    そこまで珍しいと、売る側としてももう諦めて……って感じでしょうね。 
    (2021年02月13日 15:13:53)
open/close この記事にコメントする



2021年 2月 8日

民主主義と人口ピラミッド

最近の日本やら先進国やらの迷走を見ていると、民主主義って人口ピラミッドが逆転することを考慮できていないのでは?と疑問を感じます。

人口ピラミッドが逆転して高齢世代が主流派になると、

  • 人数少の若年世代は支援しない
  • 人数多の高齢世代は支援する

このような政策が支持されるので、少子化はさらに加速し、先のない高齢世代に最大投資しまくる、まさに今の日本みたいな状態になります。当然ながら経済力は下がる一方ですし、滅亡一直線の国家です。

民主主義のバグとしか思えないですね……。

編集者: すずき(更新: 2021年 2月 27日 23:12)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 11日

デノーマルフラッシュの速度改善効果

先日(2021年 2月 5日の日記参照)非正規化数(Denormal 数)の計算は遅いと書きましたが、いかほどでしょうか?どのくらい遅いのか、デノーマルフラッシュでどの程度速くなるのか、この 2点について見ていこうと思います。

おそらく世の中のどの FPU も割り算が一番苦手なはずです。入力を正規化数、非正規化数の 2パターン用意して、下記の演算をたくさん実行してみます。

浮動小数点の割り算の速度を測るためのコード(中心部分)

#define SIZE    10000

union uuu {
	double f;
	long long n;
};

...

void test_speed(union uuu *val)
{
	for (int i = 0; i < SIZE; i++) {
		dst[i].f =
			val[i].f / 1.08f -
			val[i].f / 1.07f +
			val[i].f / 1.06f -
			val[i].f / 1.05f +
			val[i].f / 1.04f -
			val[i].f / 1.03f +
			val[i].f / 1.02f -
			val[i].f / 1.01f;
	}
}

コードは全部貼り付けると邪魔くさいので GitHub におきました(GitHub へのリンク)。前回の FTZ, DAZ のテストに使ったコードも一緒に入っています。

x86 系の CPU

まずは x86 系の CPU で測ってみましょう。手元にあるのは Zen 系(AMD Ryzen 7 2700)と、Atom 系(Intel Pentium J4205)なので、この 2つで測ります。コンパイラは gcc (Debian 10.2.1-6) 10.2.1 20210110、最適化レベルは O2 です。

Ryzen 7 2700 の結果(Linux 5.10.9-1)
10000 loops

Normal -----
FTZ:OFF, DAZ:OFF
  0.912859[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)
FTZ:OFF, DAZ:ON
  0.880695[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)
FTZ:ON, DAZ:OFF
  0.880633[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)
FTZ:ON, DAZ:ON
  0.880653[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)

Denormal -----
FTZ:OFF, DAZ:OFF
  1.806291[s]
  dst : -4.446591e-323(0x8000000000000009)
FTZ:OFF, DAZ:ON
  0.783578[s]
  dst : 0.000000e+00(0x00000000)
FTZ:ON, DAZ:OFF
  1.513203[s]
  dst : 0.000000e+00(0x00000000)
FTZ:ON, DAZ:ON
  0.783183[s]
  dst : 0.000000e+00(0x00000000)
Pentium J4205 の結果(Linux 5.4.95)
1000 loops

Normal -----
FTZ:OFF, DAZ:OFF
  1.024671[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)
FTZ:OFF, DAZ:ON
  1.025767[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)
FTZ:ON, DAZ:OFF
  1.025151[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)
FTZ:ON, DAZ:ON
  1.027414[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)

Denormal -----
FTZ:OFF, DAZ:OFF
  12.147070[s]
  dst : -4.446591e-323(0x8000000000000009)
FTZ:OFF, DAZ:ON
  0.309857[s]
  dst : 0.000000e+00(0x00000000)
FTZ:ON, DAZ:OFF
  7.126950[s]
  dst : 0.000000e+00(0x00000000)
FTZ:ON, DAZ:ON
  0.312373[s]
  dst : 0.000000e+00(0x00000000)

Ryzen 7 2700 でも Pentium J4205 でも、Denormal 数が計算に出現すると遅くなりますが、J4205 はその傾向が顕著で 10倍くらい遅いです。FTZ, DAZ を ON にすると、効果覿面に速くなります。

ARM 系の CPU

次に ARM で測ってみましょう。手元にあるのは RK3399 です。Cortex-A72 と Cortex-A53 が混載されているので、両方で測ります。カーネルは Linux 5.11.0-rc3-next-20210113、コンパイラは gcc (Debian 8.3.0-6) 8.3.0、最適化レベルは O2 です。

ARM は仕様上 FTZ と DAZ が分かれていない(FZ という両方合わせたような機能がある)ので、片方だけ ON にした結果はありません。

Cortex-A72 の結果
$ taskset 0x10 ./a.out 10000

...

10000 loops

Normal -----
FTZ:OFF, DAZ:OFF
  7.153237[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)
FTZ:ON, DAZ:ON
  7.118581[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)

Denormal -----
FTZ:OFF, DAZ:OFF
  8.008282[s]
  dst : -4.446591e-323(0x8000000000000009)
FTZ:ON, DAZ:ON
  1.779883[s]
  dst : 0.000000e+00(0x00000000)
Cortex-A53 の結果
$ taskset 0x1 ./a.out 10000

...

10000 loops

Normal -----
FTZ:OFF, DAZ:OFF
  11.693382[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)
FTZ:ON, DAZ:ON
  11.691307[s]
  dst : -3.668038e-02(0xbfa2c7c56ca81140)

Denormal -----
FTZ:OFF, DAZ:OFF
  12.196882[s]
  dst : -4.446591e-323(0x8000000000000009)
FTZ:ON, DAZ:ON
  11.697961[s]
  dst : 0.000000e+00(0x00000000)

Cortex-A72 はデノーマルフラッシュの効果抜群ですが、Cortex-A53 はデノーマルフラッシュによる変化はほとんどありません。どちらも ARM が設計した同世代の CPU にも関わらず、速度の傾向は大きく異なります。詳細な理由は ARM にしかわかりませんが、なかなか興味深い結果です。

編集者: すずき(更新: 2021年 2月 13日 02:10)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 12日

在宅勤務環境改善

COVID-19 が流行し始めた昨年 2月ころ、在宅勤務が主となりました。当時の気持ちを正直に言えば「すぐ収束して、電車通勤に戻るだろう」で、完全にナメていました。在宅勤務の環境もまったく整えておらず、ダイニングテーブル、ノート PC+8インチのモバイルディスプレイでした。夕食時は邪魔だから、仕事道具をガサガサ片付ける、といった具合です。

そんなこんなで 1年間やってきたものの、COVID-19 の予想外の長期化、それに加えて会社方針(COVID-19 が収束しようとしまいと、今後は在宅勤務)もあって、在宅勤務の環境を改善することにしました。

部屋

家には、奥さんが一昨年の在宅勤務で使っていた部屋があって、幅 100cm の机と背もたれ付きのオフィスチェアがあります。そのスペースを譲ってもらうことにしました。

  • 1年目: 奥さん在宅勤務、私は電車通勤
  • 2年目: 2人共電車通勤
  • 3年目: 奥さん電車通勤、私は在宅勤務

すっかり勤務形態が逆転しました。会社のみなさんの話を聞くと、東京の狭い家で夫婦とも在宅勤務、子供まで自粛で家に居て、全く仕事にならん……みたいな地獄化したご家庭もあるみたい。我が家も夫婦同時に在宅勤務だと、スペースの確保がちょっと大変だったと思います。交代で在宅勤務になったのは、今思えば割とラッキーだったのかな?

テーブル

ダイニングテーブルはしっかりした作りで、間違いなく家で一番上等なテーブルです。一方のダイニングチェアは年中使い続けるような椅子ではなかったらしく、1年間酷使し続けたところ、座面、背面のクッションが潰れ椅子のフレームが腰にガツガツ当たるようになりました。痛ぇよーー。

部屋を移ってスペースが広がったので、大きめのデュアルディスプレイも目指します。幅 120cm の机を買い足し 100cm の机は横向きに合わせ L字にします。

買ったのは山善の AMDT-1260 AMDL-70 という一番シンプルな天板と脚だけのテーブルですAmazon へのリンク)。Amazon で 9,000円くらいとお安いです。理由はわからないですが、山善の公式サイトには載っていないんですよね。なぜだろね?

ディスプレイ

机の幅を考えると 27インチ x2 が載りそうです。ただし、机の奥行きがあまりない(60cm)ので、大きすぎると端が見えなくなって、かえって使いにくいです。という点を勘案して 24インチ x2 にします。

買ったのは EIZO FlexScan EV2480 です。Amazon で 1台 4万円くらい。デュアルディスプレイにしたので、総額 8万円くらい掛かりました。非常に高価ですが、これでも中位機種なんです。ちなみに上位機種の EV2495 は 1台 7万円します。強烈!

FlexScan は重たいのが難点(純正スタンドがめちゃ重い)ですが、変な色やら、映らないやらのトラブルは皆無で非常に快適です。以前勤めてた会社(パナソニックやソシオネクスト)でも大変お世話になりました。良いメーカーですよね。

編集者: すずき(更新: 2021年 2月 15日 11:41)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 14日

USB Type-C DisplayPort Alternate mode

現在使っている ThinkPad E480 は USB Type-C 端子と HDMI 端子しかありません。先日(2021年 2月 12日の日記参照)新しく購入したディスプレイ 2つに画像を出力するには、USB Type-C の DisplayPort Alternate Mode(VESA の機能紹介のページ(英語))を使う必要があります。接続はこんな感じです。


E480 とデュアルディスプレイの接続

このとき E480 とディスプレイを繋ぐ USB Type-C ケーブルは 3つの役割を果たします。

  • USB 2.0/3.1 のデータ通信(ディスプレイが USB ハブになる)
  • USB Power Delivery による電力供給
  • DisplayPort Alternate Mode による画像出力

たった 1本の USB Type-C ケーブルで 3役もこなす凄いヤツです。今まで「AC アダプタ」「DisplayPort」「USB Type-A」の 3つに分かれていたコネクタが、USB Type-C 1つに統合できますから、省スペースが命のノート PC にとっては大歓迎の機能でしょう。

実はさほど便利じゃない

そんな凄いヤツを使い始めて数日ですが、既に嫌になってきました。正直な感想として、少なくともユーザーからすると便利と思えないし、使わなくて良いなら使いたくないです。

ケーブルの問題
1本で済むのは良いですが、ケーブルが硬すぎます。USB PD 対応 USB 3.1 ケーブルはかなり高速な信号を通す関係上、3重シールド 5〜6mm 幅以上のごついケーブルばかりです。これなら AC アダプタと HDMI 2本の方がまだマシです。どちらもかなり細いので。
E480 の問題
ノート PC の液晶、DisplayPort、HDMI の 3系統を使えると思いきや、3画面に拡張デスクトップを設定するとバグるので、ノート PC の液晶と DisplayPort をミラーにしています。ノート PC の液晶が完全に無意味ですが、蓋を閉めるとスリープしちゃうので、半開きでテーブルの隅に放置しています。切ない。
USB ハブの問題
ディスプレイが USB ハブの役目も果たしますが、ディスプレイの電源を切ると USB ハブとしての機能も OFF になります。マウス程度なら問題ありませんが、通信するような機器は繋ぐと毎回切られてストレス MAX です。あと USB オーディオ DAC は繋いでも動作しませんでした。何か制約があるんですかね?
USB PD の問題
ディスプレイ側の USB PD による供給力の上限は、現状 60W の製品が多いです。60W はノート PC によっては給電能力がギリギリです。ディスプレイの USB PD 供給能力が足りない場合、純正アダプタに戻して給電し出画は諦める or バッテリーを削りつつ DisplayPort Alt で出画する or ディスプレイを買い替える、究極の 3択を迫られます。

ケーブルの問題は今後、技術革新で細くなることを祈るしかありません。E480 の問題は回避策不明です。HW の制約?USB ハブの問題は、E480 なら USB Type-A コネクタが別にあるので、そちらを使えば回避可能です。USB PD の問題は今の所 E480 だと困っていません。

しかし将来的にノート PC を買い換えると USB PD の問題が起きる可能性があります。回避策はあるでしょうか?USB Type-C が 3つ付いていて、1つは DisplayPort、2つ目は USB PD 電源供給、3つ目は PC に繋ぐ、変なハブ的なものがあれば良い?もはや「ケーブル 1本で OK」のコンセプトは完全崩壊だし、ディスプレイ側の USB PD は死蔵確定です。そんな訳のわからんことになるなら、素直に DisplayPort と USB Type-C のコネクタ 2個付けてくれよって思います。

そもそも DislayPort と USB PD なんて全く無関係のものを統合したら、どちらか壊れただけで PC が機能不全になることくらい、聡明な VESA や USB-IF の面々には明らかなはずですけど、何でこんなデザインにしたんですかね?理解しがたいよ……。

USB PD と DisplayPort Alt Mode を見ると思い出すのは、あの商品

昔 SHARP SF1 という製品がありました(DIME の記事)。スーパーファミコンとテレビが 1つに合体した、当時小学生だった私には夢のような製品でした。配線なしで見た目スッキリ、場所も取らない、AC アダプタやビデオケーブルを接続する手間も不要、いかにも便利そうじゃないですか?結構お高いのもあって、友達が持っているのを見て羨ましかったです。USB Type-C も似たような売り文句です。

しかし後から聞くところによれば、テレビが故障するとスーパーファミコンを外せないから他のテレビに繋げなくて困る、逆にスーパーファミコンが故障するとテレビごと修理になって高ぇわテレビがなくなるわで困る、元より不便になっています。元々バラバラの製品を無理やり一蓮托生にしたら、そりゃそうなりますわな……。無関係の機能をデタラメに統合してはいけない、という好例です。

残念なことに USB Type-C も DisplayPort と USB PD の機能統合で、似たような落とし穴に落ちています。小学生の私に「21世紀になっても人類は SF1 と同じ過ちを繰り返しているよ」って教えてあげたいですね。

編集者: すずき(更新: 2021年 2月 15日 21:33)

コメント一覧

  • hdk 
    テレビデオも壊れたときがと聞いて買いませんでしたが、狭い学生宿舎で数年使えればいいだけならあれも手だったのかもとは思います。
    USB Type-Cのハブは、一本させば全部つながるというのなら、外して会議室や外出先に持ち出し・戻ってつなぐ用途では楽になりそうです。同様に使えるドッキングステーションやウルトラベースもありましたよね。 
    (2021年02月15日 06:24:17)
  • すずき 
    そうですね、1年だけとか、出張の時だけ、といった使い方にはとても便利だと思います。
    今回は常用したかったので、困りました。DisplayPort Alt mode は存在していただいて構わないんですけど、代わりの機能がないところが一番困ったところです。 
    (2021年02月15日 11:27:33)
open/close この記事にコメントする



2021年 2月 15日

Wikipedia の数学のページを眺める

群とか環とか体とか、大学で教えてもらった記憶がうっすらありますが、何回見ても忘れます。幸いにも Wikipedia 先生に割と詳しく解説されているので、まとめておこうと思います。

集合 G と二項演算 u の組(G, u)を考えます。u は乗法や加法と呼ばれる場合があるようです。以降 u(a, b) を a + b の形で表します。

半群
閉性を満たす: 二項演算 u(u: G + G -> G)の結果は G に含まれる
結合法則を満たす: a + (b + c) = (a + b) + c
モノイド
単位元 e が存在する: a + e = e + a、整数の加法でいえば 0
逆元 x が存在する: a + x = x + a = e 整数の加法でいえば -a
アーベル群
交換法則を満たす: a + b = b + a

下にある群は、上の群の性質をすべて満たします(以降も特に断りがなければ同じ)。なので、モノイドは半群の性質を満たしますし、群はモノイドと半群の性質を満たします。

集合 R と 2つの二項演算 u, t の組(R, u, t) を考えます。(R, u) はアーベル群です。u は加法、t は乗法と呼ばれるようです。以降 t(a, b) を a * b の形で表します。

乗法半群
閉性を満たす: 二項演算 t(t: R * R -> R)の結果は R に含まれる
結合法則を満たす: a * (b * c) = (a * b) * c
乗法モノイド
単位元 e が存在する: a * e = e * a、整数の乗法でいえば 1
環(モノイドでない場合がある)
加法の上に左分配律を満たす: a * (b + c) = (a * b) + (a * c)
加法の上に右分配律を満たす: (a + b) * c = (a * c) + (b * c)
可換環(モノイドでない場合がある)
交換法則を満たす: a * b = b * a

群と違って、環はモノイド(単位元が存在する)である必要はないみたいです。

零因子

可換環では零でない零因子という困ったことが起きます。

  • a * x = 0 となる x != 0 が存在するとき a は左零因子
  • y * a = 0 となる y != 0 が存在するとき a は右零因子

困る例として挙げられていたのは a * b = 0 かつ a != 0 でも b = 0 とは限らない、もしくは、a * b = a * c かつ a != 0 でも、b = c とは限らない、という例でした。

具体的な例が載ってませんでしたが、行列の和と積を考えると発生しそうに思えます。

左零因子になるかな?
A =
[1, 1]
[0, 0]

B =
[ 1, 0]
[-1, 0]

C =
[0, -1]
[0,  1]

A * B =
[0, 0]
[0, 0]

A * C =
[0, 0]
[0, 0]

A != 0 だが B, C は零行列ではない。A * B = A * C だが、B = C でもない。

環はこういうパターンが無数に出てきて、さらに条件を厳しくしないと困る場合がありますよ、ということですかね?

整域

変わった名前ですが、環の一種のようです。環で発生する零因子による困った問題を排除しています。

整域(乗法モノイドである必要がある)
零が唯一の零因子: a * x = 0 かつ a != 0 ならば x = 0
非自明環: 自明環(零のみの集合は {0} 環となるので、自明環と呼ばれる)ではない

力尽きた

群環体の「体」まで辿り着きたかったのですが、整閉整域、一意分解整域、主イデアル整域、ユークリッド整域、体、有限体、と訳のわからない名前のオンパレードで、力尽きました。また今度調べます。

編集者: すずき(更新: 2021年 2月 16日 01:52)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 16日

一般のご家庭に PC は何台ある?

内閣府の「主要耐久消費財等の普及率」「主要耐久消費財の保有数量の推移」(リンク)によると、2人以上の世帯の PC 普及率は 77.0%、100世帯辺り 123.6台(2020年 3月)だそうです。

保有世帯だけを考えれば 123.6 / 0.77 / 100 = 1.61 [台/世帯] ですから、世帯人数 < PC 台数です。PC を日常的に使う習慣がない限り、共有の PC が 1台あれば十分ですし、納得感ある結果です。

一般のご家庭に PC は何台置ける?

では、一般のご家庭に PC は最大で何台置けるでしょうか?

PC の消費電力は様々ですが、夢はでっかく、高性能 PC として、AMD Threadripper 3990X, NVIDIA GeForce RTX 3090 のマシンを考えましょう。CPU とグラボの TDP は 280 + 350W = 630W です。他の部品や損失を考えると、PC 1台あたり 800W 程度と思われます。

一般家庭の我が家の電気契約(40A)ですと、5台程度でブレーカーが飛びます。200V 系のコンセントを増設し、200V で給電すれば電流は半減するので 10台くらいは置けるでしょう。30A 契約のご家庭も多いでしょうから、「高性能 PC 8〜10台」これが一般のご家庭の限界と思われます。

逸般の誤家庭に PC は何台置ける?

では、色々逸脱した逸般の誤家庭の場合はどうでしょうか?

家庭の電気契約は「従量電灯 B」という契約(従量電灯 B・C 電気料金プラン - 東京電力エナジーパートナー株式会社)がほとんどです。従量電灯 B の最大契約アンペア数は 60A で、全て 200V から取ると最大 12kW です。したがって 12000 / 800 = 15台が限界です。ふーむ、意外と伸びませんね。

冷却の電力は完全に無視しています。冷却を無視したまま 15台も置いたら、家の中は一瞬で灼熱地獄になり、人間も PC も死ぬと思います。

業務用なら青天井

大口需要向けに「従量電灯 C」という契約もあります。

従量電灯 C の場合 10A ごとに基本料金が従量的に増える青天井の契約になります。一般家庭でも契約可能のようです。基本料金を比較すると、従量電灯 B < 従量電灯 C となるため、一般のご家庭だと損するだけで契約する意味はありません。

本来、家電が大量にある豪邸や、業務用の電気機器がある商店用ですが、60A に満足できない真の逸般の誤家庭にも向いているかもしれませんね。

編集者: すずき(更新: 2021年 2月 28日 00:27)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 25日

Slideshare 初利用

Slideshare を初めて使いました。LinkedIn のアカウントが必要なのは知りませんでした。偶然 LinkedIn のアカウントを持っていたので、すんなり登録できました。

USB PD はもっとわかりやすくしてほしい

試しに USB Type-C, USB PDケーブルとお友達になろうをアップロードしました。ダウンロードもできるし、スライド置き場として優秀ですね。みんな使うわけだ……。

スライドの話もしておくと、USB Type-C ケーブルがどうして何種類もあって、値段が全然違うのか、気になったので調べたことをまとめたものです。USB 初心者なので間違ってたらすみません。

最後まで分からなかったのは USB Power Delivery の 3A/5A ケーブルを見分ける方法です。何か無いんでしょうか。当然 USB PD のアナライザで見ればわかりますよ?でもアナライザなんか普通の人は持ってませんよ。パッケージから出した途端に見分けが付かなくなるなんて、一般消費者からしてみたら辛すぎません?

編集者: すずき(更新: 2021年 2月 28日 00:58)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2021年 2月 27日

新キーボード購入

先日の在宅勤務環境改善(2021年 2月 12日の日記参照)にて、デュアルディスプレイにしたところ、ノート PC 本体が邪魔になってしまったので、机の上からどけました。

当然、ThinkPad 本体のキーボードには手が届きませんから、ワイヤレスキーボード Logicool K295 を買いました。Amazon で 1,900円くらいでした。K295 は変なキーも少ないし、静かで良いですが、キーの認識が渋いです。私の場合、打鍵力が足りず人差し指担当のキー(T, U など)の誤打が多発してイライラします。

買ってすぐ買い替えるのもどうかと悩みましたけど、あまりに誤打が多く慣れるまで辛そうだったので、さっさと諦め FILCO の Majestouch 赤軸を買いました。ヨドバシで 15,000円くらいでした。Majestouch はキーが戻るとき&底打ちしたとき「カーン!」と響く鐘のような音がやかましい以外は、非常に良いキーボードです。

キーボード使用歴

今まで、キーボードは 標準的なキーボード(※)であれば、高くても安くても使い心地が気になることはないと思っていました。しかし今回 K295 がどうも合わなかったことから、実は自分とキーボードの相性って結構あるのか?と疑問に感じるようになりました。

(※)OADG 109A 型の配列で、カーソルキー、ファンクションキー等の位置を移動していないキーボードのこと。

まずはキーボードの使用履歴を書き出してみます。

相性とか全く気にならなかった。

  • DELL の標準キーボード
  • Gateway の標準キーボード
  • HP の標準キーボード
  • IBM/Lenovo ThinkPad X, E シリーズ
  • Logicool K270
  • Majestouch 赤軸
  • NEC VersaPro
  • Owltech の安いキーボード
  • RealForce 108UBK
  • サンワサプライの安いキーボード
  • SONY VAIO Type-G
  • TOSHIBA Dynabook R73

誤打しやすかった。

  • Let's Noteシリーズ(理由: キーの形が横長)
  • Logicool K295(理由: キーの認識が渋い)
  • Logicool K340(理由: カーソル、ファンクションキー配置が変)

まともに打てなかった。

  • HappyHacking(理由: キー配置が変すぎる)

以前 K340 や HHK で懲りて、特殊なキー配列のキーボードに触らなくなったので、コンパクト系のキーボードの利用歴はほぼゼロです。そもそもまともに打てないし、レビューできません。

ほとんど PC 付属キーボード、ノート PC のキーボードばかりです。これはもしや、勝手に安物だと思いこんでいた PC 付属の標準キーボード、実は質が高かったのではなかろうか?

大事な製品に標準で付属するものですし、高級ではないにせよ、あまりに変なものはつけませんよね。これが答えなのでは、という気がしてきました。

編集者: すずき(更新: 2021年 2月 28日 03:50)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



こんてんつ

open/close wiki
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報