コグノスケ


link 未来から過去へ表示  link 過去から未来へ表示(*)

link もっと前
2020年7月12日 >>> 2020年8月11日
link もっと後

2020年7月12日

MAD Tower Tycoonコンプリート

目次: ゲーム

MAD Tower Tycoonでゾーン方式のエレベータの作り方を悩んで色々やっていたら、いつのまにかレベル100、実績コンプリートしていました。ゲーム内時間は表示されないので詳しくはわかりませんが、おそらく700日くらい?


MAD Tower Tycoon実績コンプリート

The Towerと比べて色々思うところはありますが、総合的にみれば面白いと思います。

序盤だけ金欠になりやすいですが、難易度はかなり低めですし、ビル建築シミュレーション初めての方にオススメしたいゲームです。

高層ビルを作りたい

MAD Tower Tycoonは住人を追尾する機能があり、ビルの住人が困っていないか把握するのに便利です。基本的には目的地に行って、家に帰る(住人の場合)、もしくはビルから出る(ゲストの場合)だけですけど、大きなビルを作ると変な行動が目立ちます。

  • ビルの端から端まで歩いて、わざわざ遠いエレベーターで乗り換え
  • 近所のレストランを無視して、わざわざ遠いレストランに行く

前回(2020年7月10日の日記参照)も書きましたが、MAD Tower Tycoonはゾーン方式のエレベーターを作る方法がわかりません。今はメンテナンス施設の射程(上下6Fに効果がある)の関係で、7階+8階(※)おきに乗り換え階を作っています。

どうもこの方式だと40階くらいで限界っぽいです。乗り換えに時間が掛かりすぎて、目的地に行くだけで半日費やしている気の毒な住民がいます。彼らはなぜか不満は言いませんが、見ていると不憫です……。

救いとしてはMAD Tower Tycoonはビルの横幅がめちゃくちゃ広く取れるので、45階もあれば、レベル100、五つ星ビルが余裕で作れることです。だけど、やっぱりThe Towerにあやかるなら、100階建て目指したいですよね?

(※)効率重視ならば7F, 14F乗り換えが最適ですが、スカイロビーを作成できるのは15Fからなので、あえて14Fを空きフロアにして、15F乗り換えにしています。

どうしてもThe Towerと比較してしまう

MAD Tower Tycoonは、The Towerとかなり似ているがゆえに、つい比較してしまいます。

良いところ

  • エレベータ乗り換えがロビー階以外でも可能
  • 何度でも乗り継げる(1F → 7F → 15F → 23Fのような乗り継ぎが可能)
  • かなり上の階でも階段で行ける(The Towerは確か4Fくらいしか上らない)

悪いところ

  • エレベータの通過階設定ができない(今、一番困っている制限)※通過階設定はできるが設定が効かないバグ、とのこと(2023/10/20追記)
  • 一度上に行ってから、下に行く乗り換えが不可能(1F → 15F → 7Fみたいな乗り換えはしないようだ)

ゾーン方式のエレベーターが作れたら、高層ビルに効率的に人を運べるようになって、もっと面白くなるはずなのに。もったいないよ〜。

編集者:すずき(2023/10/20 03:51)

コメント一覧

  • わしださん(2020/08/10 22:36)
    The Tower懐かしいですね。
    話題とずれる荒しみたいなコメントになりますが、旧姓でエゴサーチして最も古い自分の名前が出るのが、Geocitiesの他人のサイトに投稿したThe towerのビルでした。小6くらいだったのですが、本名とビル名に「第百ビル」とか付けてて。
    その10年以上後、新卒で会社入って最初の移動先の課長に「第百ビルの人?」って聞かれてびびりました。(会社入って一年くらいは旧姓だったので)
    いまはGeocitiesも閉鎖になったので出てきませんが、いい思い出ではあります。
    ということでとにもかくにも100階建てにしてチャペル建てたくなる気持ちを思い出しました。
  • すずきさん(2020/08/11 18:59)
    小学生でサイトに投稿はスゴイです。そして会社バレしてるのも奇遇というかなんというか。
    The Tower で遊んでいたのは、たしか中学生時代だったと思いますが、当時インターネットとかパソコン通信はさっぱりわからず、ビルを投稿しようという考えが全くなかったです。
    Mad Tower Tycoon も 100階にチャペルを建てられますが、The Tower ほどの重要なポジションではない(集客施設の一つに過ぎない)です。星 3〜4辺りからゲーム性が極端に下がってダレてしまうのも、ちょっと残念なポイントです。
  • 通り縋りさん(2023/10/18 19:08)
    上の記事2023年9月編集という事ですが間違ってます。
    2023年10月現在、正しくは「エレベーターの通過階設定自体は出来るが正確に反映されない」です。
    通過階設定自体は出来る事を確認してますが、特に高速エレベーターに於いて設定が正常に反映されず「通過階にも待ちが発生し停車してしまう」というバグとなっています。
  • すずきさん(2023/10/19 11:17)
    ご指摘ありがとうございます。9月の編集は先頭にリンクを加えただけで、内容は2020年7月に書いたときのままです。わかりにくくてすみません。
    それは良いとして、ご指摘の内容に合わせて修正しておきます。
open/close この記事にコメントする



2020年7月13日

STATIONflow - まとめリンク

目次: ゲームに統合。

編集者:すずき(2024/06/03 23:57)

コメント一覧

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



2020年7月14日

OpenCLとICD

目次: OpenCL

OpenCLは複数のベンダーのデバイスを同時に扱うことができます。ICD(Installable Client Driver)というそうです。ICDはGPUなどのデバイスを制御し、アプリケーションとICDの間にICDローダーが存在します。


アプリケーション、ICDローダー、ICDの関係


Debianでのライブラリ名

Debian TestingではICDローダーとしてocl-icd-2.2.12が使われています。

Debian TestingのICD loader
$ apt-cache search ocl-icd-libopencl1

ocl-icd-libopencl1 - Generic OpenCL ICD Loader

ローダーのソースコードはGitHub(リンク)にあります。

先程、図示したもの以外にもICDはいくつか実装があります。現時点のDebian Testingでは下記が提供されていました。

  • pocl-opencl-icd: 主にCPU向け
  • beignet-opencl-icd: 比較的古いIntel GPU向け
  • intel-opencl-icd: 比較的新しいIntel GPU向け、Testingにしか存在しない
  • mesa-opencl-icd: AMD GPU向け
  • nvidia-opencl-icd: nVidia GPU向け、ソースコードは公開されていない

IntelはICDのソースコードを完全にオープンにしています。NVIDIAは公開していません。AMDもないのかな?

ICDのロード手順

動作を追ってみたいと思います。アプリケーションにはclinfoを使います。ocl-icdは環境変数OCL_ICD_DEBUG=15に設定すると、動作時に詳細なログを出力します。デバッガで追うのと併用するとわかりやすいです。

  • clinfo: clGetPlatformIDs() を呼ぶ
  • ocl-icd: _initClIcd() -> _initClIcd_real() -> __initClIcd()
  • ocl-icd: _find_num_icds(): /etc/OpenCL/vendorsの *.icdファイルを見る(*.soへのパスが書いてある)
  • ocl-icd: _load_icd(): *.soをdlopen()
  • ocl-icd: _find_and_check_platforms(): 後述

ローダーが走査するディレクトリは /etc/OpenCL/vendorsがハードコードされていますが、環境変数OPENCL_VENDOR_PATHで変更できます。

ICDのロードの中心となる処理は _find_and_check_platforms() です。

  • dlsym() でclGetExtensionFunctionAddress() のアドレスを得る
  • clGetExtensionFunctionAddress() でclIcdGetPlatformIDsKHR() のアドレスを得る
  • clGetExtensionFunctionAddress() でclGetPlatformInfo() のアドレスを得る
  • clIcdGetPlatformIDsKHR() でプラットフォーム数とプラットフォームの情報を得る

プラットフォームは説明が難しいですが、OpenCL APIの実体+任意のドライバ固有のデータとでも言いましょうか。変数の型はcl_platform_id * 型です。cl_platform_idは少なくとも先頭のメンバはstruct _cl_icd_dispatch *dispatchでなければなりません。dispatchの後ろには他の情報が入っていても問題ないようです。

cl_platform_idとdispatch

// ocl-icd/ocl_icd_loader.c

static inline void _find_and_check_platforms(cl_uint num_icds) {
  cl_uint i;

...

    cl_platform_id *platforms = (cl_platform_id *) malloc( sizeof(cl_platform_id) * num_platforms);
    error = (*plt_fn_ptr)(num_platforms, platforms, NULL);

...

    for(j=0; j<num_platforms; j++) {
      debug(D_LOG, "Checking platform %i", j);
      struct platform_icd *p=&_picds[_num_picds];
      char *param_value=NULL;
      p->extension_suffix=NULL;
      p->vicd=&_icds[i];
      p->pid=platforms[j];    //★★pid = platform IDのことらしい

      /* If clGetPlatformInfo is not exported and we are here, it
       * means that OCL_ICD_ASSUME_ICD_EXTENSION. Si we try to take it
       * from the dispatch * table. If that fails too, we have to
       * bail.
       */
      if (plt_info_ptr == NULL) {
        plt_info_ptr = p->pid->dispatch->clGetPlatformInfo;    //★★dispatchメンバが存在することを前提としている

      
// ocl-icd/khronos-headers/CL/cl.h

typedef struct _cl_platform_id *    cl_platform_id;


// ocl-icd/(build-dir)/ocl_icd_loader_gen.h

struct _cl_platform_id { struct _cl_icd_dispatch *dispatch; };    //★★dispatch以外は特に規定がなさそう


// ocl-icd/(build-dir)/ocl_icd.h

struct _cl_icd_dispatch {
#ifdef CL_VERSION_1_0
  CL_API_ENTRY cl_int (CL_API_CALL*clGetPlatformIDs)(
    cl_uint          /* num_entries */,
    cl_platform_id * /* platforms */,
    cl_uint *        /* num_platforms */
  ) CL_API_SUFFIX__VERSION_1_0;
#else
  CL_API_ENTRY cl_int (CL_API_CALL* clUnknown0)(void);
#endif

#ifdef CL_VERSION_1_0
  CL_API_ENTRY cl_int (CL_API_CALL*
  clGetPlatformInfo)(
    cl_platform_id   /* platform */,
    cl_platform_info /* param_name */,
    size_t           /* param_value_size */,
    void *           /* param_value */,
    size_t *         /* param_value_size_ret */
  ) CL_API_SUFFIX__VERSION_1_0;
#else
  CL_API_ENTRY cl_int (CL_API_CALL* clUnknown1)(void);
#endif

...

//★★こんな調子で関数ポインタの定義が延々と続く

先頭のdispatchはたくさんの関数ポインタが並んだ巨大な構造体です。アプリケーションから見るとOpenCLのAPIはocl-icdが提供しているように見えますが、ocl-icdのAPI実装はdispatchの関数ポインタを呼ぶラッパー関数であり、関数ポインタと、OpenCL API実装の本体を提供するのは各ICDの役割です。

編集者:すずき(2023/09/24 11:57)

コメント一覧

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



2020年7月15日

GCCを調べる - その16 - 自動ベクトル化を有効にする

目次: GCC

GCCには自動ベクトル化(tree-vectorize)機能があります。ループ処理を自動的にSIMD命令に置き換えるために使われているようです。現状のGCCが可変長のベクトル長に対応しているかどうかはわかりません。未対応ならば可変長のベクトル長に対応する実装が必要になりますが、非常に難しそうです。

可変長のベクトルの扱いはひとまず横に置くとして、RISC-Vのベクトルを「とても長い固定長のSIMD」とみなして自動ベクトル化を動かします。

自動ベクトル化を有効にするコード

// gcc/config/riscv/riscv.c

/* Implement TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES.  */

static unsigned int
riscv_autovectorize_vector_modes (vector_modes *modes, bool)
{
  if (TARGET_VECTOR)
    {
      modes->safe_push (V64SImode);
      modes->safe_push (V32SImode);
    }

  return 0;
}

...

#undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES
#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES riscv_autovectorize_vector_modes

自動ベクトル化を有効にする方法は簡単で、これだけです。

テスト用のint配列をコピーする関数

void *cpy(void *dst, const void *src, int n)
{
	int *d = dst;
	const int *s = src;
	int i;

	for (i = 0; i < n / sizeof(*d); i++) {
		d[i] = s[i];
	}

	return dst;
}

この関数がベクトル化あり、なしでどのように変わるか見ます。

自動ベクトル化の結果

//★★自動ベクトル化、あり

                d[i] = s[i];
   100b8:       1202e007                vlw.v   v0,(t0)
   100bc:       10038393                addi    t2,t2,256
   100c0:       f0038793                addi    a5,t2,-256
   100c4:       10028293                addi    t0,t0,256
   100c8:       0207e027                vsw.v   v0,(a5)
        for (i = 0; i < n / sizeof(*d); i++) {
   100cc:       fee296e3                bne     t0,a4,100b8 <cpy+0x44>
   100d0:       00661293                slli    t0,a2,0x6
   100d4:       02568963                beq     a3,t0,10106 <cpy+0x92>
   100d8:       959a                    add     a1,a1,t1
   100da:       932a                    add     t1,t1,a0
                d[i] = s[i];
   100dc:       0005a383                lw      t2,0(a1)


//★★自動ベクトル化、なし

                d[i] = s[i];
   10080:       0005a303                lw      t1,0(a1)
        for (i = 0; i < n / sizeof(*d); i++) {
   10084:       0591                    addi    a1,a1,4
   10086:       0291                    addi    t0,t0,4
                d[i] = s[i];
   10088:       fe62ae23                sw      t1,-4(t0)
        for (i = 0; i < n / sizeof(*d); i++) {
   1008c:       fe759ae3                bne     a1,t2,10080 <cpy+0xc>
        }

        return dst;
}
   10090:       8082                    ret

ソースコードではベクトル型を使っていませんが、自動ベクトル化により256バイト(=64要素)ずつ処理され、vlw.v, vsw.v命令が使われるようになったことがわかります。

編集者:すずき(2023/09/24 11:52)

コメント一覧

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



2020年7月18日

北極送り

GitHubが北極にコードを保存する取り組み(私のソースコードが北極送りに? "GitHub" アカウントに謎のラベルが付与されたとの報告が多数 - やじうまの杜 - 窓の杜)をしているそうです。面白いこと考えますよね。


GitHub Arctic Code Vault Contributor

気づいたら自分のGitHubアカウントにもArctic Code Vault Contributorと出ていました。有名なOSSには関わってないし縁がないと思っていましたが、どうやらLinuxにコントリビュートしていたので出てきたっぽいです。いわれてみるとLinuxもGitHubにミラーされてました。

未来人は現代人を理解できるだろうか?

現代人をもってしても1000年前の文字の解読(例: ヒエログリフ、前3200年〜4世紀、19世紀頃に解読された)はとても苦労したこと、解読されていない古代文字がまだまだあることを考えれば、現代文字や文明を遺しても未来人が理解不能で終わってしまう可能性もあるわけです。

少なくとも未来文明は現代文明より遥か上の水準に発展していないと、仮に現代文字や文明を発見できても、真に理解するのは難しいでしょう。

こんなことを考えると、実はCode Vaultの取り組みは「地球の未来は今より進んでいるはず」という信頼や願望が前提になっていることが見て取れます。人類か、それ以外の生命体か、誰の手に渡るかわかりませんが、SF的なロマンがありますよね。

編集者:すずき(2020/07/23 12:53)

コメント一覧

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



2020年7月19日

GCCを調べる - その17 - ベクトル四則演算、論理演算の定義

目次: GCC

ベクトルのロード、ストアだけでは自動ベクトル化できるコードが少なすぎるので、他の演算も定義したいと思います。

ベクトル演算の加算、減算、乗算、除算、論理演算(and, or, xor)の定義

;; gcc/config/riscv/riscv.md

(define_attr "vecmode" "unknown,V32SI,V64SI"
  (const_string "unknown"))

...

;; Iterator for hardware supported vector modes.
(define_mode_iterator ANYV [(V32SI "TARGET_VECTOR")
			    (V64SI "TARGET_VECTOR")])

...


;;★★加算

(define_insn "add<mode>3"
  [(set (match_operand:ANYV	       0 "register_operand" "=v")
	(plus:ANYV (match_operand:ANYV 1 "register_operand" " v")
		   (match_operand:ANYV 2 "arith_operand"    " v")))]
  "TARGET_VECTOR"
  "vadd.vvt%0,%1,%2"
  [(set_attr "type" "arith")
   (set_attr "vecmode" "<MODE>")])


;;★★減算

(define_insn "sub<mode>3"
  [(set (match_operand:ANYV		0 "register_operand" "=v")
	(minus:ANYV (match_operand:ANYV 1 "register_operand" " v")
		    (match_operand:ANYV 2 "arith_operand"    " v")))]
  "TARGET_VECTOR"
  "vsub.vvt%0,%1,%2"
  [(set_attr "type" "arith")
   (set_attr "vecmode" "<MODE>")])


;;★★乗算

(define_insn "mul<mode>3"
  [(set (match_operand:ANYV	       0 "register_operand" "=v")
	(mult:ANYV (match_operand:ANYV 1 "register_operand" " v")
		   (match_operand:ANYV 2 "arith_operand"    " v")))]
  "TARGET_VECTOR"
  "vmul.vvt%0,%1,%2"
  [(set_attr "type" "arith")
   (set_attr "vecmode" "<MODE>")])


;;★★除算

;; This code iterator allows unsigned and signed division to be generated
;; from the same template.
(define_code_iterator any_div [div udiv mod umod])

(define_insn "<optab><mode>3"
  [(set (match_operand:ANYV		  0 "register_operand" "=v")
	(any_div:ANYV (match_operand:ANYV 1 "register_operand" " v")
		      (match_operand:ANYV 2 "arith_operand"    " v")))]
  "TARGET_VECTOR"
  "v<insn>.vvt%0,%1,%2"
  [(set_attr "type" "arith")
   (set_attr "vecmode" "<MODE>")])


;;★★論理演算

;; This code iterator allows the three bitwise instructions to be generated
;; from the same template.
(define_code_iterator any_bitwise [and ior xor])

...

(define_insn "<optab><mode>3"
  [(set (match_operand:ANYV		      0 "register_operand" "=v")
	(any_bitwise:ANYV (match_operand:ANYV 1 "register_operand" "%v")
			  (match_operand:ANYV 2 "arith_operand"    " v")))]
  "TAREGET_VECTOR"
  "v<insn>.vvt%0,%1,%2"
  [(set_attr "type" "logical")
   (set_attr "vecmode" "<MODE>")])

四則演算、論理演算を使う下記のプログラムを書きます。自動ベクトル化で四則演算のループをベクトル化しても良いですが、ベクトル拡張記法(Vector Extensions (Using the GNU Compiler Collection (GCC)))を使ったほうが狙った演算が出しやすく、テストするときに楽です。

ベクトル四則演算、論理演算のサンプルプログラム

typedef int __v64si __attribute__((__vector_size__(256)));

void test()
{
	__v64si v10, v11, v12, v13;0;

	__asm__ volatile ("vlw.v %0, %1\n" : "=&v"(v10) : "A"(b[10]));
	__asm__ volatile ("vlw.v %0, %1\n" : "=&v"(v11) : "A"(b[20]));
	__asm__ volatile ("vlw.v %0, %1\n" : "=&v"(v12) : "A"(b[30]));
	__asm__ volatile ("vlw.v %0, %1\n" : "=&v"(v13) : "A"(b[40]));

	v10 = v11 + v12;
	v11 &= v12 - v13;
	v12 |= v13 * v10;
	v13 ^= v10 / v11;

	__asm__ volatile ("vsw.v %1, %0\n" : "=A"(b[40]) : "v"(v10));
	__asm__ volatile ("vsw.v %1, %0\n" : "=A"(b[50]) : "v"(v11));
	__asm__ volatile ("vsw.v %1, %0\n" : "=A"(b[60]) : "v"(v12));
	__asm__ volatile ("vsw.v %1, %0\n" : "=A"(b[70]) : "v"(v13));
}

ビルド方法は何でも良いですが、最適化レベルをOgにするとアセンブラが見やすいと思います。

ベクトル四則演算、論理演算のサンプルプログラム(逆アセンブル)
$ riscv32-unknown-elf-gcc b.c -nostdlib -g -Og -march=rv32gcv -mabi=ilp32f

$ riscv32-unknown-elf-objdump -dS a.out

...

        __asm__ volatile ("vlw.v %0, %1\n" : "=&v"(v13) : "A"(b[40]));
   10092:       0a028793                addi    a5,t0,160
   10096:       1207e207                vlw.v   v4,(a5)

        v10 = v11 + v12;
   1009a:       022081d7                vadd.vv v3,v2,v1
        v11 &= v12 - v13;
   1009e:       0a120057                vsub.vv v0,v1,v4
   100a2:       26010057                vand.vv v0,v0,v2
        v12 |= v13 * v10;
   100a6:       9641a157                vmul.vv v2,v4,v3
   100aa:       2a208157                vor.vv  v2,v2,v1
        v13 ^= v10 / v11;
   100ae:       863020d7                vdiv.vv v1,v3,v0
   100b2:       2e1200d7                vxor.vv v1,v1,v4

        __asm__ volatile ("vsw.v %1, %0\n" : "=A"(b[40]) : "v"(v10));
   100b6:       0207e1a7                vsw.v   v3,(a5)

...

うまくいっているようです。良かった良かった。

編集者:すずき(2023/09/24 11:52)

コメント一覧

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



2020年7月20日

GCCを調べる - その18 - ベクトルNot演算の定義

目次: GCC

前回(2020年7月19日の日記参照)は四則演算と論理演算(and, or, xor)を定義しました。今回はNot演算を定義します。他の論理演算と異なり、Not演算は2オペランドしか取りませんから、define_insnを別に書く必要があります。

ベクトルNot演算の定義

;; gcc/config/riscv/riscv.md

(define_insn "one_cmpl<mode>2"
  [(set (match_operand:ANYV           0 "register_operand" "=v")
	(not:ANYV (match_operand:ANYV 1 "register_operand" "%v")))]
  "TARGET_VECTOR"
  "vnot.vt%0,%1"
  [(set_attr "type" "logical")
   (set_attr "vecmode" "<MODE>")])

前回同様に、ベクトル拡張記法(Vector Extensions (Using the GNU Compiler Collection (GCC)))を使ってビット毎Notを使うプログラムを書きます。

ベクトルNot演算のサンプルプログラム

typedef int __v64si __attribute__((__vector_size__(256)));

void test()
{
	__v64si v10, v11;
	static int b[1024 * 1024] = {0};

	__asm__ volatile ("vlw.v %0, %1\n" : "=&v"(v10) : "A"(b[10]));
	__asm__ volatile ("vlw.v %0, %1\n" : "=&v"(v11) : "A"(b[20]));

	v10 = ~v11;

	__asm__ volatile ("vsw.v %1, %0\n" : "=A"(b[40]) : "v"(v10));
}

コンパイルするとエラーが発生します。何かお気に召さないようです。

コンパイルエラー
$ riscv32-unknown-elf-gcc b.c -nostdlib -Og -march=rv32gcv -mabi=ilp32f

during RTL pass: reload
dump file: b.c.282r.reload
b.c: In function 'test':
b.c:14:1: internal compiler error: in setup_operand_alternative, at lra.c:814
   14 | }
      | ^
0xea5c36 setup_operand_alternative
        gcc/gcc/lra.c:814
0xea70c2 lra_set_insn_recog_data(rtx_insn*)
        gcc/gcc/lra.c:1073
0xea30f9 lra_get_insn_recog_data
        gcc/gcc/lra-int.h:488
0xeab0b9 remove_scratches_1
        gcc/gcc/lra.c:2058
0xeab4c4 remove_scratches
        gcc/gcc/lra.c:2094
0xeac629 lra(_IO_FILE*)
        gcc/gcc/lra.c:2396
0xe1a41f do_reload
        gcc/gcc/ira.c:5523
0xe1ae5c execute
        gcc/gcc/ira.c:5709

コードを見ると最後のオペランドに % を付けるべきではないそうです。確かにdefine_insnを見ると % が要らないのに付いています。

エラーを出している箇所

// gcc/lra.c

/* Setup info about operands in alternatives of LRA DATA of insn.  */
static void
setup_operand_alternative (lra_insn_recog_data_t data,
			   const operand_alternative *op_alt)
{
  int i, j, nop, nalt;
  int icode = data->icode;
  struct lra_static_insn_data *static_data = data->insn_static_data;

  static_data->commutative = -1;
  nop = static_data->n_operands;
  nalt = static_data->n_alternatives;
  static_data->operand_alternative = op_alt;
  for (i = 0; i < nop; i++)
    {
      static_data->operand[i].early_clobber_alts = 0;
      static_data->operand[i].is_address = false;
      if (static_data->operand[i].constraint[0] == '%')    //★★% が付いていればcommutative
	{
	  /* We currently only support one commutative pair of operands.  */
	  if (static_data->commutative < 0)
	    static_data->commutative = i;
	  else
	    lra_assert (icode < 0); /* Asm  */
	  /* The last operand should not be marked commutative.  */
	  lra_assert (i != nop - 1);    //★★このアサートに引っかかる
	}
    }

...

素直に応じるとエラーは消えます。

ベクトル演算のNotの定義(修正後)

(define_insn "one_cmpl<mode>2"
  [(set (match_operand:ANYV           0 "register_operand" "=v")
	(not:ANYV (match_operand:ANYV 1 "register_operand" " v")))]    ★★% を消す
  "TARGET_VECTOR"
  "vnot.vt%0,%1"
  [(set_attr "type" "logical")
   (set_attr "vecmode" "<MODE>")])

四則演算、論理演算(3オペランド系)と、Not演算(2オペランド系)が揃いました。残りの頻出する演算はビットシフト系かな?

最後のオペランドをcommutativeにできない理由

最後のオペランドをcommutativeにしてはいけない理由は、GCCのConstraintsの説明を見るとわかります。

`%' Declares the instruction to be commutative for this operand and the following operand. This means that the compiler may interchange the two operands if that is the cheapest way to make all operands fit the constraints. GCC can only handle one commutative pair in an asm; if you use more, the compiler may fail. Note that you need not use the modifier if the two alternatives are strictly identical; this would only waste time in the reload pass. The modifier is not operational after register allocation, so the result of define_peephole2 and define_splits performed after reload cannot rely on `%' to make the intended insn match.

難しいことを言っていますが、commutativeは % を付けたオペランドと「次」のオペランドが可換だと宣言することだそうです。最後のオペランドには「次」のオペランドがありませんから、% を付けてはいけません。なるほど。

RISC-Vの場合は論理演算のdefine_insnの2番目のオペランドに % が使われています。

RISC-Vスカラ論理演算の定義

;; gcc/config/riscv/riscv.md

;; This code iterator allows the three bitwise instructions to be generated
;; from the same template.
(define_code_iterator any_bitwise [and ior xor])

...

(define_insn "<optab><mode>3"
  [(set (match_operand:X                0 "register_operand" "=r,r")
	(any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
		       (match_operand:X 2 "arith_operand"    " r,I")))]
  ""
  "<insn>%i2t%0,%1,%2"
  [(set_attr "type" "logical")
   (set_attr "mode" "<MODE>")])

例えばand r1, r2, r3とand r1, r3, r2は結果が同じですから、2番目と3番目のオペランドは入れ替え可能です。3つの論理演算(any_bitwiseはand, or, xorのこと)はいずれも同様に入れ替え可能ですので、このような定義になっています。

編集者:すずき(2023/09/24 11:52)

コメント一覧

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



2020年7月21日

ARM SBCリスト2

目次: ROCK64/ROCKPro64

最近はたくさんのARMのシングルボードコンピュータ(SBC)が市販されています。2019年以降のボードも追加してみました。値段は変動するので参考です。

Amlogic S905X3
ボードHardkernel ODROID-C4, A55/2.0GHz x 4, 4GB DDR4-2666, 12nm, $50, 2020/04
Amlogic A311D (S922X + NPU)
ボードKhadas KVIM3-P-002, A73/2.2GHz x 4, A53/1.8GHz x 2, 4GB LPDDR4-????, 12nm, $160, 2019/06
Amlogic S912
ボードKhadas KVIM2-M-002, A53/1.5GHz x 8, 3GB DDR4-????, 28nm, $170, 2017/08
Broadcom BCM2711
ボードRaspberry Pi 4 Model B, A72/1.5GHz x 4, 8GB LPDDR4, 28nm, $75, 2019/11
HiSilicon Kirin 970
ボード96boards HiKey 970, A73/2.36GHz x 4, A53/1.8GHz x 4, 6GB LPDDR4-1866, 10nm, $299, 2018/??
MediaTek Helio X20
ボード96boards MediaTek X20, A72/2.1GHz x 2, A53/1.85GHz x 4, A53/1.4GHz x 4, 2GB LPDDR3-????, 20nm, $199, 2017/??
NVIDIA Xavier AGX
ボードNVIDIA Jetson Xavier AGX, Carmel/2.26GHz x 8, 8MB L2, 4MB L3, 32GB LPDDR4-2133, 12nm, $700, 2020/??
NVIDIA Xavier NX
ボードNVIDIA Jetson Xavier NX, Carmel/1.4GHz x 6, 6MB L2, 4MB L3, 8GB LPDDR4-1600, 12nm, $400, 2020/??
Rockchip RK3399
ボードFriendlyARM NanoPC-T4, A72/2GHz x 2, A53/1.5GHz x 4, 4GB LPDDR3-1866, 28nm, $109, 2018/??
Samsung S5P6818
ボードFriendlyARM NanoPC-T3 Plus, A53/1.4GHz x 8, 2GB DDR3, $75, 2018/??

古い世代のSoCを採用したボード達です。

AllWinner H6
ボードPINE64 PINE H64, A53 x 4, 2GB LPDDR3-1600, 28nm, $36
AllWinner H5
ボードFriendlyARM NanoPi NEO2, A53/1.5GHz x 4, 1GB DDR3, 40nm, $20
Amlogic S905
ボードHardkernel ODROID-C2, A53/1.5GHz x 4, 2GB DDR3-1866? (912MHz), 28nm, $39
Broadcom BCM2837B
ボードRaspberry Pi 3 Model B, A53/1.2GHz x 4, 1GB LPDDR2, 28nm, $35
HiSilicon Kirin 960
ボードHiKey 960, A72 x 4, A53 x 4, 3GB LPDDR4, 16nm FinFET, $239
NVIDIA Tegra X2 (Parker)
ボードJetson TX2, Denver/2GHz x 2, A57/2GHz x 4, 8GB LPDDR4, 16nm, $600
NVIDIA Tegra X1
ボードJetson TX1, A57/1.9GHz x 4, 4GB LPDDR4, 20nm, $500
Rockchip RK3328
ボードPINE64 ROCK64, A53/1.4GHz x 4, 4GB LPDDR3-1866, 28nm, $24.95 (1GB) $34.95 (2GB) $44.95 (4GB)

以前(2019年5月15日の日記参照)載せた情報も含んでいます。

編集者:すずき(2023/09/24 12:54)

コメント一覧

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



2020年7月28日

またバッテリー死す

目次:

コロナ騒ぎが始まって、遠出することもなくなり、かれこれ4か月以上?車に乗らず放置していました。

骨折した奥さんを整形外科におくるため、JAFさんに車のバッテリー上がりを直してもらったんですけど、バッテリー電圧がなんと1Vしかありません。えー??

車のバッテリー(鉛蓄電池)の端子電圧は12V程度が正常ですから、10Vの見間違い?と思いましたけど、何回見ても1.0Vでした。乾電池だってもうちょっと電圧あるでしょう。

今まで何度となくバッテリー上がりさせ、バッテリー破壊もこれで4度目(2007年、2013年、2016年、2020年)ですけど、1Vまで下がったのは初めてです。

割とお高いGS YUASA 80D23L大容量バッテリーを使っていたのですが、いかなるバッテリーであろうと、このレベルの過放電には無力ですね。エンジン掛かった後も全く充電される気配がありませんでした。

近所のイエローハットまでバッテリー交換しに行く道中が一番嫌でした。

  • 4か月ぶりの運転
  • バッテリー電圧が12V〜11Vくらいでグラグラ
  • アイドリングが不調で止まりそう(バッテリー上がりでエンジンの調整データが消えた?)
  • エンストしたら二度と掛からない

こんな状態で、産業道路〜環七〜第二京浜と走るのはかなり怖いです。無事に辿り着けて良かったけども。

また懲りずにPanasonic 85D23Lの大容量バッテリーに交換しておきました。3万円くらいしました。たっけぇ……。今年は車検もあるし、全然乗ってない割に金ばっかり掛かってます。不思議ですね。

メモ: 技術系の話はFacebookから転記しておくことにした。

編集者:すずき(2023/09/30 14:45)

コメント一覧

  • hdkさん(2020/07/30 21:40)
    さすがに月イチくらいは動かしてあげてください...
    ウチの原付は中古で買ってから8年半以上経っているんですが、バッテリーはそのままで未だにエンジン始動できています。買った半年後にやや電圧が低いようなことを言われていたのに、不思議です。
  • すずきさん(2020/07/30 22:19)
    乗る用事はないし、乗ろうと思って、いつも忘れてしまうんですよね。。。
open/close この記事にコメントする



2020年8月1日

ROCKPro64と音声ビットストリームパススルー出力

目次: ROCK64/ROCKPro64

去年だったか、ROCKPro64のHDMI音声出力を有効化するパッチをlinux-nextに送ろうとしたことがあります。当時のレビューコメントでSPDIFとHDMIの音声ビットストリームパススルー出力(※1)は動くか?と聞かれたものの、テスト環境がなかったため、わからないまま挫折してしまいました。

今回、再チャレンジにあたり、テスト用にSPDIFとHDMIの音声ビットストリームをデコードできる機械を探しました。これがどうして、お手頃価格の良い商品が見当たらないです。

AmazonではSPDIFのみ対応の商品がありました。メーカーが怪しい、色んなバージョンが色んな店から売られている、そもそも動くの??など不安は募りますが、ダメ元で購入しました。

大手メーカー製を探すと、ホームシアター用ヘッドホンシステム3〜4万円、もしくはAVプリアンプ10万円over!のような大げさな商品しかありません。

音声ビットストリームパススルー出力が、いかに高コスト&需要がないか良くわかりました。普通の人は音声信号がLPCMかパススルーかなど細かいことは気にしませんから、当然の成り行きでしょうね。

(※1)音声信号としてLPCMではなく、Dolby Digital(AC-3)やDTSをデコードせず圧縮音声のままSPDIFやHDMIに出力する方式のことです。デコードは受信機器側で行います。

SPDIF用のテスト機材

SPDIFパススルーのテスト用に、中国製と思われる謎の機械(型番なし、筐体にはHD AUDIO RUSHと書いてある)を購入しました。Amazonで4,000円くらいです。安い!事前の不安をよそに音は正常に鳴っています。素晴らしいです。

しかし本体にコーデックのインジケータがなく、LPCMか音声ビットストリームか全く判別がつきません。テスト用の機材としてはイマイチでした。10分に1回くらいSPDIF信号のPLLロックが外れた(?)と思われる、数秒レベルの音切れが発生します。ROCKPro64の出す信号が悪いのか、HD AUDIO RUSHが悪いのか、切り分けできず真因は不明です。

SPDIFだけだとLPCM 96kHz 16bit 2ch(3.072Mbps)のような、SPDIF(Max 1.5Mbps)の帯域を超える音声信号はテストできません。無理やり流すと酔っ払いが演奏してるみたいな変な音になります。HD AUDIO RUSHくん以外にHDMI用のテスト機材が必要です。

HDMI用のテスト機材

HDMIのテストならテレビ(Panasonic TH-L37DT3)で確認できるだろ、と思っていたら、HDMI音声入力はLPCM 2chのみの対応でした。LPCMは2ch以外にも5.1ch出力(※2)がありますがテストできません。ダメだこれ。

覚悟を決めてサラウンドヘッドフォンシステムSONY MDR-HW700DSを注文しました。37,000円くらいします、高い!まだ家に届いていませんが、来週辺りかな、人生初のSPDIF/HDMI音声ビットストリームパススルー対応機器が手に入ります。

(※2)身近な例でいうとNintendo Switchのサラウンドモードが、LPCM 5.1ch出力を使います。試しにSwitchをサラウンドモードにすると、テレビから全く音が出ませんでした。がっかり。

編集者:すずき(2020/10/30 01:05)

コメント一覧

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



2020年8月2日

ROCKPro64のHDMIから音を出すKconfig設定

目次: ROCK64/ROCKPro64

今更ですが、メモしていなかった気がするので、ROCKPro64(Rockchip RK3399搭載)でHDMI Audioを有効にする方法です。

方法は簡単でLinuxのCONFIG_DRM_DW_HDMI_I2S_AUDIOと、CONFIG_GPIO_SYSCONを有効にすれば良いです。8/7時点のlinux-nextのツリーでは、make defconfigすると、GPIO_SYSCONはnで、ビルド対象外になっています。手動で下記の設定を有効にする必要があります。

linux-nextで有効にするコンフィグ(元から有効になっているものも含む)
  Device Drivers  --->
    -*- GPIO Support  --->
      Memory mapped GPIO drivers  --->
        [*] GPIO based on SYSCON
    Graphics support  --->
      Display Interface Bridges  --->
        [*] Synopsys Designware I2S Audio interface
    [*] Sound card support  --->
      [*]   Advanced Linux Sound Architecture  --->
        [*]   ALSA for SoC audio support  --->
          CODEC drivers  --->
            [*] Everest Semi ES8316 CODEC

CONFIG_SND_SOC_ES8316はアナログオーディオを使いたい場合に有効にしてください。

編集者:すずき(2020/10/30 01:05)

コメント一覧

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



2020年8月3日

ROCKPro64とSPDIF/HDMIビットストリームパススルー

目次: ROCK64/ROCKPro64

以前(2020年8月1日の日記参照)購入したSONY MDR-HW700DSが届きました。早速ROCKPro64でHDMIのビットストリームパススルーをテストしたいと思います。

おさらい

ビットストリームパススルーは、SPDIFやHDMIに対して、圧縮音声データ(Dolby AC-3, DTS, MPEG2 AACなど)をデコードせず、そのまま送信する方式です。この方式の最大の利点としては、サラウンド音声が楽しめる点が挙げられます。

SPDIFは帯域が狭く、デコード後のサラウンド音声(LPCM 5.1ch)を送れません。しかしSPDIF上を圧縮音声のまま送信し、受信機であるホームシアターシステム側で音声をデコードすることで、SPDIFでもサラウンド音声が楽しめます

HDMIの場合は利点がないかと言うとそうでもありません。LPCM 5.1chを送出できない機器もありますし、ホームシアターシステムに適したデコードやミキシングができる可能性もあります。

パススルーのやり方

SPDIF/HDMIパススルーに対応したプレイヤーはいくつかあるようですが、今回はmpvを使用します。

GitHubにあるALSAのコンフィグファイル(GitHubへのリンク)を ~/.asoundrcなどに追記します。再生時にaudio-spdifオプションで出力フォーマットを指定します。再生するファイルの音声フォーマットと合っていれば、パススルーで出力されます。

パススルーあり
$ mpv --no-video a.ac3 --audio-spdif=ac3 --audio-device="alsa/HDMI.pcm.hdmi.0:0"

Playing: a.ac3
[ffmpeg/demuxer] ac3: Estimating duration from bitrate, this may be inaccurate
 (+) Audio --aid=1 (ac3 6ch 48000Hz)
AO: [alsa] 48000Hz stereo 2ch spdif-ac3    ★AC3になっている
A: 00:00:02 / 00:05:36 (0%)


HDMIにDolby AC-3をパススルーで出力

SONY MDR-HW700DSのステータス画面は本体のインジケーターではなくHDMIの画像データにオーバーレイするタイプなので、HDMIディスプレイの写真を取りました。狙い通りにAC-3が再生されている様子がわかります。

オプションを間違えたり、オーディオデバイス番号を間違えてもエラーにはならず、再生が開始されますが、パススルーではなくデコードされLPCMで再生が開始されます。

パススルーなし(オーディオデバイスを指定し間違えた例)
$ mpv --no-video a.ac3 --audio-spdif=ac3 --audio-device="alsa/hw:0"    ★間違えてhw:0にした

Playing: a.ac3
[ffmpeg/demuxer] ac3: Estimating duration from bitrate, this may be inaccurate
 (+) Audio --aid=1 (ac3 6ch 48000Hz)
ALSA lib conf.c:4898:(parse_args) Unknown parameter AES0
ALSA lib conf.c:5031:(snd_config_expand) Parse arguments error: No such file or directory
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM hw:0,AES0=6,AES1=130,AES2=0,AES3=2
[ao/alsa] Playback open error: No such file or directory
[ao] Failed to initialize audio driver 'alsa'
[ao] This audio driver/device was forced with the --audio-device option.
[ao] Try unsetting it.
AO: [alsa] 48000Hz stereo 2ch s32    ★LPCMになっている
A: 00:00:02 / 00:05:36 (0%)


HDMIにLPCMで出力

その他の注意点として、受信機側がパススルー出力で送った圧縮音声に対応していない場合、LPCMだと思って再生してしまい、バリバリバリ!!という凄まじい音量のノイズが再生されることがあります。お試しの際は、音量を小さくしてからテストしてください。

編集者:すずき(2020/10/30 01:11)

コメント一覧

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



2020年8月6日

エアコンが落ちそうで怖い

Twitterで「これ便利」と紹介されているのを見て知りました(製品紹介へのリンク)。エアコンハンガーというそうです。見た瞬間から「うわー!やめてくれー…エアコンは物干しじゃない」という感想しか浮かびません。

エアコン据付板の耐荷重はマチマチで、耐荷重ギリギリの可能性もあります。ハンガーの耐荷重(5kg)を追加で吊って、エアコン室内機が頭の上に落ちてきたら大ケガします(室内機の重さは10〜15kg)。

パナソニックのエアコン説明書にある山盛りの注意書きを見ましたが「エアコンにモノを吊り下げると、落下しケガする」とは書いていませんでした。家電のユーザーはメーカー想定を超える壊し方をすることは、一応知ってましたが、実例を目の当たりにしたのは初めてです。全く嬉しくないですね。

エアコンハンガーの利用で、事故やケガにあっている人がいないことを祈ります……。 ちなみに、エアコンハンガーのメーカー注意書きに、

「下地がしっかりしていない壁に取り付けられているエアコンには使用しないでください。エアコンが落下する恐れがあります。(例: 下地にベニア板の無い石膏ボードなど)」

と言い訳が書いてありますが、一般人が壁の素材と下地を知るわけないでしょう?本気で言ってるのか??

メモ: 技術系?の話はFacebookから転記しておくことにした。

編集者:すずき(2020/08/08 14:24)

コメント一覧

  • hdkさん(2020/08/08 14:57)
    言い訳がいいですね。実際にもし石膏ボードをボリボリと壊して落下したとして、室外機との接続があるから床までは落ちないんですかね。傾くくらいで済むのかな。
  • すずきさん(2020/08/10 17:53)
    室内の銅配管は段々硬くなるので、床に落ちることはないと思います。
    とはいえ、うちのように結構室内の配管が長いと、頭には当たるかもしれないですね。
open/close この記事にコメントする



2020年8月7日

Wikipedia

Wikipediaに寄付しました。といっても5,000円ですけども。

Wikipediaの運営元(Wikimedia Foundation, Inc.)は広告なしでWikipediaのような巨大システムを維持していて、さすがだと思いますけど、寄付催促メールのしつこさはちょっと嫌ですね……。

メモ: 技術系?の話はFacebookから転記しておくことにした。

編集者:すずき(2020/08/08 14:24)

コメント一覧

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



2020年8月8日

レガシィ5回目の車検

目次:

車検証と検査証票(フロントガラスに貼るステッカー)が届きました。

いつもならディーラーさんに1週間くらい預けるので、車検証もそのときに付いてきます。今回は奥さんの通院の送り迎えに車が必要で、スバルのディーラーさんに無理を言って土日月の3日で車検を終わらせてもらいました。

車検の検査自体は終わっても、車検証の発行が間に合わなかったので、後から郵送されてきた、ってことです。

検査内容

リアのロアアームブッシュが破損していたので、交換になった程度で、他は特に何もありませんでした。部品の在庫があって良かったです。

編集者:すずき(2023/09/30 15:10)

コメント一覧

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



2020年8月11日

エナジードリンクとお国柄

マクドナルドが各国で味付けが違うのは有名ですが、エナジードリンクにもお国柄があってUSA版のMonster Energyはタウリンあり、日本版はタウリンなしの製品が販売されています。これはRed Bullも同様です。ただしエナジードリンクの場合、味付けの問題ではなく法律の問題です。

日本では、タウリンを入れると医薬部外品になり、製造業者+販売業者の厚労省の許可、商品ごとに承認が必要になります。Monster Energy製造、販売元のアサヒ飲料は清涼飲料水製造メーカーなので、医薬部外品製造の設備は持っていないでしょう。たぶん。

実はヒトはタウリンを外部から摂取しなくても、体内で生合成できますから、生合成の原料となる物質を入れれば良いじゃない?と思うかもしれませんが、そんな甘くありません。厚生労働省の告示(リンク)(※)を見るとわかる通り、タウリンの主要な合成経路「L-メチオニン → L-システイン → タウリン」のいずれも医薬部外品扱いで清涼飲料水には添加できません。

L-メチオニンは必須アミノ酸なので生合成不可能、すなわち他の成分をいくら入れても代用になりません。必須アミノ酸は全て医薬部外品として指定されている辺り、良くできた法律です。

薬事法の目的「保健衛生の向上」を見る限り、必須アミノ酸を規制する意味ある……?という気になりますけど、一方で「医薬品、医療機器及び再生医療等製品の研究開発の促進」という目的もあります。苦労して薬効成分を見つけた製薬会社、高価な製造設備を入れているメーカーの権益を保護してあげるから、これからも医療品の研究開発を頑張ってくれたまえ〜!という法律なんですね。なるほどねえ。

(※)厚生省告示第百九十四号 - 都道府県知事の承認に係る医薬部外品という文書名です。

編集者:すずき(2020/08/15 18:10)

コメント一覧

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



link もっと前
2020年7月12日 >>> 2020年8月11日
link もっと後

管理用メニュー

link 記事を新規作成

<2020>
<<<07>>>
---1234
567891011
12131415161718
19202122232425
262728293031-

最近のコメント5件

  • link 24年6月17日
    すずきさん (06/23 00:12)
    「ありがとうございます。バルコニーではない...」
  • link 24年6月17日
    hdkさん (06/22 22:08)
    「GPSの最初の同期を取る時は見晴らしのい...」
  • link 24年5月16日
    すずきさん (05/21 11:41)
    「あー、確かにdpkg-reconfigu...」
  • link 24年5月16日
    hdkさん (05/21 08:55)
    「システム全体のlocale設定はDebi...」
  • link 24年5月17日
    すずきさん (05/20 13:16)
    「そうですねえ、普通はStandardなの...」

最近の記事3件

  • link 24年4月12日
    すずき (07/05 10:40)
    「[台湾東部沖地震に寄付] ささやかではありますが台湾東部沖地震に寄付しました。日本の赤十字社→台湾の赤十字(正式名称...」
  • link 24年4月16日
    すずき (07/05 10:40)
    「[Zephyr SDKのhosttoolsは移動してはいけない、その2 - インストール時のバイナリ書き換え] 目次: Zep...」
  • link 24年4月17日
    すずき (07/05 10:39)
    「[VSCodeとMarkdownとPlantUMLのローカルサーバー] 目次: LinuxVSCodeのPlantUML Ex...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
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 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

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

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 07/05 10:40