コグノスケ


2015年 10月 2日

ジージェネレーションフロンティア

SD ガンダム ジージェネレーションフロンティアの話。今までの FR 設計イベントをメモしておきます。

FR 設計イベントの材料一覧
第一弾

FR アカツキ(シラヌイ)/ 誘導機動ビーム砲塔システム
-- UR ゲーマルク(覚醒)/マザー&チルド・ファンネル
-- UR シナンジュ /バズーカ
-- UR ドム/ジェットストリームアタック
-- UR デスティニーガンダム(最大稼働)/パルマフィオキーナ

第二弾

FR νガンダム/連続格闘
-- UR クロスボーン・ガンダムX1改・改/ヒートダガー&スクリュー・ウェッブ
-- UR サザビー/ファンネル(Ver.2)
-- UR ジ・O(覚醒)/ビーム・ソード/四刀流 
-- UR アルトロンガンダム/ドラゴンハング

第三弾

FR ガンダムアヴァランチエクシア/GNソード/ソードモード
-- UR ストライクルージュ(IWSP)/一斉発射
-- UR ノイエ・ジール/有線クロー・アーム
-- UR ∀ガンダム/核弾頭
-- UR ケルディムガンダムGNHW(トランザム)/GNライフルビット

第四弾

FR ガンダムデルタカイ/プロト・フィン・ファンネル
-- UR グフ・カスタム/ヒート・ワイヤー
-- UR ガンダムDX(Gファルコン)/ツインサテライトキャノン
-- UR デストロイガンダム/ツォーンMk2&スーパースキュラ
-- UR デルタガンダム/ビーム・サーベル/二刀流

第五弾

FR ガンダムAGE-2ノーマル/MS/ハイパードッズライフル
-- UR ザクII改/ヒート・ホーク&ダミーバルーン爆弾
-- UR トールギスIII/メガキャノン/最大出力
-- UR ガンダムAGE-1ノーマル/ドッズライフル
-- UR ラフレシア/親バグ&子バグ

これらのイベントは既に終わっていますが、しばらく経つと再実施されるようです。作り逃した FR キャラクターが居ても、後でまた作れるかもしれませんので、材料となる UR キャラクターを、間違って処分してしまわないようにメモしておきます。

しばらくやってみた感想

楽しい点は、小学生の時にハマっていた SD ガンダムのカードダス集めの気分が味わえることです。特に FR キャラクター(カードダスのキラキラカードに相当)が当たった時は、出たこれ!って気分で嬉しいですね。

ゲームとしてはつまらないです。もし同じ面を 100回以上やる「イベント」を、毎週連発するだけのゲームが面白い!好き!と思う人が居ればオススメしますが…。私は立ちながらか、歩きながらプレイしないと確実に寝ます。

嫌いな点は UI です。いちいちボタンを押さないと進まないのに、ボタンの配置に統一感がありません。片手で遊びづらいです。

編集者: すずき(更新: 2015年 10月 4日 03:49)

コメント一覧

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



2015年 10月 4日

ちぐはぐな Visual Studio のエディタとコンパイラ

Visual Studio 2015 のコンパイラは、未だに BOM を付けないと UTF-8 を認識しません。なぜか Shift-JIS もコンパイルエラーになります(2013 ではなりません)。

MSDN ライブラリ(サイトへのリンク)でも「コンパイラおよびリンカーでの Unicode のサポート(... 中略 ...)BOM 付きの UTF-8」などと言いきる始末です。イマイチすぎる…。

Visual Studio の IDE は Git に対応したり、エディタがマルチプラットフォームになったり、コミュニティベース開発に力を入れたり、時代の流れに沿って進化していますが、

コンパイラはダメダメ感が漂います。C++0x の対応は llvm, gcc の後塵を拝しワーストです。もはや Microsoft ですら単独で C/C++ コンパイラを開発するのは不可能なのかなあ…?

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

編集者: すずき(更新: 2015年 11月 29日 03:53)

コメント一覧

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



2015年 10月 5日

MPEG4-AVC / H.264 の 2つのフォーマット

今や映像の圧縮方式として当たり前となりつつある MPEG4-AVC(※)には、2つの形式があります。

  • ISO/IEC 14496-1: Annex B - Byte Stream Format
  • ISO/IEC 14496-15: NAL File Format

Byte Stream Format は、俗に言うスタートコード形式(0x000001 を目印として NALU が始まる)で、コンテナを使わない場合、リアルタイム配信(RTSP)、放送系(MPEG2-TS をコンテナ)で良く使われているようです。

利点としては「欠け」に強いことです。何か問題が発生してデータが欠けてしまっても、スタートコードさえ見つかれば、その地点から処理を再開できます。その分、毎度スタートコードを探す処理が必要がある、先頭が欠けても再生できるように重複して情報を入れる必要があるなど、やや非効率的です。

NAL File Format は、いわゆるサイズ指定形式(数バイトのサイズの後に NALU が始まる)です。ファイル形式(MP4 など)に良く使われているようです。

利点としては「効率的」であることです。余分な情報はコンテナに持たせて、ビットストリームからは取り去りますのでサイズが小さくできます。NALU のサイズも予めわかりますから不要な NALU をスキップする際の負荷も低いです。その分、1バイトでも欠けてしまうと、デコードできなくなってしまう弱さもあります。

実はこの 2つを変換するのは面倒で、サイズ指定をスタートコードに置き換えるだけではダメです。そんな単純な変換では、上記のような特徴が出せません…。

(※)AVC は Advanced Video Codec の略です。この規格は ISO/IEC と ITU-T の共同規格なので、MPEG4-AVC ではなく ITU-T の規格名である H.264 と呼ぶ人も多いですね。

変換ツールの使い方

でも、自分でそのような処理を書く必要はありません。世の中にはナイスガイ達が居て、変換が可能なツールを公開してくれています。ありがたいことです。

まずは ffmpeg を使う場合ですが、コーデックは変更しないので copy を指定して、普段の利用ではあまり見かけない bsf オプションを使って変換します。

なぜ mp4toannexb という名前かと言うと、MPEG4-AVC の規格である ISO/IEC 14496-1 Annex B に Byte Stream Format の規格が示されているからではないか?と思われます。

ffmpeg を使う場合(NAL File Format から Byte Stream Format)
avconv -i /path/to/hogehoge.mp4 -vcodec copy -bsf:v h264_mp4toannexb hogehoge.h264

Gstreamer を使う場合は h264parse エレメントを使います。ffmpeg と比べるとかなり長く感じますが、大したことはしていないです。

例では、改行を入れていますが、実際には改行を入れずに 1行で書いてください。もし Gstreamer 1.0 系を使う場合は、video_00 のところを video_0 と書く必要があったはずです。たぶん。

gstreamer を使う場合(NAL File Format から Byte Stream Format)
 gst-launch filesrc location=/path/to/hogehoge.mp4 ! 
 qtdemux name=dem dem.video_00 ! 
 h264parse ! 
 video/x-h264,stream-format=byte-stream,alignment=au ! 
 filesink location=/path/to/es/hogehoge.h264

普通に動画を楽しんでいる人には、こんな変換は全く縁がありませんが、私にとっては便利なんです。こんなツール達がオープンソースで公開されているというのは、ありがたいことですなー…。

編集者: すずき(更新: 2015年 10月 11日 18:12)

コメント一覧

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



2015年 10月 9日

Apple とファウンドリ

「うわ... 私の iPhone 6s バッテリーもたない?」 CPU 違いの 6s でバッテリーベンチをしてみました を読んで。

元々の原価が低いのか、FinFET で首位に立つべく値引きしたか、事情は知りませんが、廉価版の iPhone ほど Samsung 製の搭載比率が大きいところを見ると、TSMC より Samsung の方が Apple の利ザヤがデカいのでしょう。おそらく。

そういえば Qualcomm は Snapdragon 810(TSMC 20nm)で発熱問題に泣いて、次の Snapdragon 820 は Samsung 製らしいですね。16nm 世代を採用したら次も泣かされそう…。

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

編集者: すずき(更新: 2015年 10月 10日 01:02)

コメント一覧

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



2015年 10月 10日

Linux の初期化順序

Linux 用のデバイスドライバを書くときは module_init(関数名) と書いて、初期化関数を指定します。

ドライバをカーネルモジュール(*.ko)としてビルドしたときは、insmod した時に初期化関数が実行されます。これは想像に難くないですし、初期化関数に printk でも入れておけば簡単に確認できます。

では…、ドライバを Linux カーネルに組み込んだ時は、一体いつ初期化処理が実行されるのでしょうか?Linux には他のドライバも含まれていますが、実行される順序に決まりはあるでしょうか?

わたくし恥ずかしながら、この辺の仕組みを全く理解していなかったので、コードを調べてみました。既に同じような事を調べている人がいる気がしてなりませんが…まあ良いや。

Linux の初期化関数

Linux の初期化は、linux/init/main.c の start_kernel() から始まります。start_kernel() は山のように初期化を実行していますが、我らが module_init() の実行に関係しているのは下記の部分です。

Linux のエントリ関数から、ドライバの初期化関数まで、その 1

start_kernel()
  rest_init()
    kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

ここでカーネルスレッドが作成され、スレッドのエントリ関数は kernel_init() です。で、続けて追いかけます。

Linux のエントリ関数から、ドライバの初期化関数まで、その 2

kernel_init()
  kernel_init_freeable()
    do_basic_setup()
      do_initcalls()
        do_initcall_level()
          do_one_initcall()
            initcall_levels[level][n]()

このような順で呼ばれます。この initcall_levels が今回の話のキモとなります。initcall_levels は下記のように定義されています。

ドライバの初期化関数群

typedef int (*initcall_t)(void);

extern initcall_t __initcall_start[];
extern initcall_t __initcall0_start[];
extern initcall_t __initcall1_start[];
extern initcall_t __initcall2_start[];
extern initcall_t __initcall3_start[];
extern initcall_t __initcall4_start[];
extern initcall_t __initcall5_start[];
extern initcall_t __initcall6_start[];
extern initcall_t __initcall7_start[];
extern initcall_t __initcall_end[];

static initcall_t *initcall_levels[] __initdata = {
        __initcall0_start,
        __initcall1_start,
        __initcall2_start,
        __initcall3_start,
        __initcall4_start,
        __initcall5_start,
        __initcall6_start,
        __initcall7_start,
        __initcall_end,
};

コードを見る限り、二重配列 __initcall_levels は __initcalln_start という配列を要素として持っていること、__initcall0_start[0], __initcall0_start[1], __initcall0_start[2], ... の順に関数ポインタが先に呼び出され、その後も同様に __initcall1_start, __initcall2_start, ... と続いて __initcall7_start に入っている関数ポインタは後に呼び出されることがわかります。

しかし肝心の __initcall0_start に何の関数ポインタが入るのか?はわかりません。それもそのはず、実は C のコード上に、これら __initcallx_start 配列の定義はありません。別の方法で定義されているのです。

この __initcall0_start 〜 __initcall7_start 配列は、あるマクロで宣言された初期化関数のポインタを全て持つ配列となります。対応関係は下記の通りです。

  • __initcall0_start: pure_initcall()
  • __initcall1_start: core_initcall()
  • __initcall2_start: postcore_initcall()
  • __initcall3_start: arch_initcall()
  • __initcall4_start: subsys_initcall()
  • __initcall5_start: fs_initcall()
  • __initcall6_start: device_initcall()
  • __initcall7_start: late_initcall()

なぜそうなるか?は後述しますので、とりあえずこんな関係があることだけ頭の隅に置いてください。

おまじない module_init() の正体

カーネルモジュールを作るとき、初期化関数を指定するためのおまじないとして module_init(funcname) と書きますが、これは実はマクロで linux/include/linux/module.h にて、下記のように定義されています。

module_init() マクロの定義

/**
 * module_init() - driver initialization entry point
 * @x: function to be run at kernel boot time or module insertion
 *
 * module_init() will either be called during do_initcalls() (if
 * builtin) or at module insertion time (if a module).  There can only
 * be one per module.
 */
#define module_init(x)  __initcall(x);

#define __initcall(fn) device_initcall(fn)

#define device_initcall(fn)             __define_initcall(fn, 6)

マクロの定義は module_init = __initcall = device_initcall となっていますので、module_init(funcname) は device_initcall(funcname) と書くのと同じです。

最後に module_init(funcname) は __define_init(funcname, 6) と定義されています。これもマクロで linux/include/linux/init.h に下記のように定義されています。

__define_init() マクロの定義

#define __define_initcall(fn, id) \r        static initcall_t __initcall_##fn##id __used \
        __attribute__((__section__(".initcall" #id ".init"))) = fn

何だか小難しいですが、簡単に言うと module_init(funcname) つまり __define_initcall(funcname, 6) と書いたら、初期化関数 funcname のポインタを値に持つ __initcall_funcname6 という名前の変数を宣言し、セクション .initcall6.init に置け、という意味になります。

その変な名前の変数がどこに置かれるのか?は、リンカスクリプト linux/arch/arm/kernel/vmlinux.lds に書いてあります。全部は載せられませんので .initcall6.init セクションに言及しているところを見てみます。

リンカスクリプトと __initcall_funcname6 の行き先

 .init.data : {
    *(.init.data) *(.meminit.data) *(.init.rodata) *(.meminit.rodata) . = ALIGN(8);
    __clk_of_table = .;
    *(__clk_of_table) *(__clk_of_table_end) . = ALIGN(32);
    __dtb_start = .;
    *(.dtb.init.rodata) __dtb_end = .;
    . = ALIGN(16);
    __setup_start = .;
    *(.init.setup) __setup_end = .;
    __initcall_start = .;
    *(.initcallearly.init) __initcall0_start = .;
    *(.initcall0.init) *(.initcall0s.init) __initcall1_start = .;
    *(.initcall1.init) *(.initcall1s.init) __initcall2_start = .;
    *(.initcall2.init) *(.initcall2s.init) __initcall3_start = .;
    *(.initcall3.init) *(.initcall3s.init) __initcall4_start = .;
    *(.initcall4.init) *(.initcall4s.init) __initcall5_start = .;
    *(.initcall5.init) *(.initcall5s.init) __initcallrootfs_start = .;
    *(.initcallrootfs.init) *(.initcallrootfss.init) __initcall6_start = .;
    *(.initcall6.init) *(.initcall6s.init) __initcall7_start = .; ★★これ★★
    *(.initcall7.init) *(.initcall7s.init) __initcall_end = .;
    __con_initcall_start = .;
    *(.con_initcall.init) __con_initcall_end = .;
    __security_initcall_start = .;
    security_initcall.init) __security_initcall_end = .;
    ...

※本来は改行が入っていませんが、見やすいように適宜改行を入れています。

私はリンカスクリプトに明るくないので、間違っていたらごめんなさいですが、基本的には書いた順でシンボル(変数や関数など)をオブジェクトファイル内に並べてくれる、という理解でこの辺りは大丈夫なはずです。

先ほどの __define_initcall() マクロの定義から __initcall_funcname6 変数は、コンパイラが .initcall6.init というセクションに入れて、オブジェクトファイルを生成します。わかりにくいと思うので、例で説明します。

例えば、リンカが今までシンボルを並べてきた結果、現在のアドレスが 0x10000 になっていたとします。あと .initcall6.init セクションには __initcall_funcname6 と __initcall_func2name6 の 2つのシンボルが含まれているとします。

リンカはまず「__initcall6_start = .;」を見て、現在のアドレス(ドットは現在のアドレスを表す)に 0x10000: __initcall6_start を定義します。現在のアドレスは変わりません。

次に「*(.initcall6.init)」を見て、全オブジェクトファイルの .initcall6.init のシンボルを順番に並べ、現在のアドレスを進めます。つまり 0x10000: __initcall_funcname6, 0x10004: __initcall_func2name6 が並び、現在のアドレスは 0x10008 になります。「*(.initcall6s.init)」も同様ですが、何もシンボルが入っていないのでスルーします。

最後に「__initcall7_start = .;」を見て、0x10008: __initcall7_start を定義します。

すなわち下記のようなアドレス、シンボルの関係になります。

- Linux カーネル
  - セクション A
  - セクション B
  - セクション .init.data
      - ...
      - 0x10000: __initcall6_start
      - .initcall6.init 内の全シンボル
        (内訳)
        - 0x10000: __initcall_funcname6  = funcname() のポインタ
        - 0x10004: __initcall_func2name6 = func2name() のポインタ
      - 0x10008: .initcall6s.init 内の全シンボル
      - __initcall7_start
      - .initcall7.init 内の全シンボル
      - ...
  - セクション D
  ...

ここで、序盤の謎であった __initcall6_start の謎が解けます。思い出してほしいのですが、変数 __initcall_xxxx6 は device_initcall(xxxx, 6) で指定した関数 xxxx のポインタを値として持っていました。

リンカスクリプトによって、変数 __initcall_xxxx6 の一群を __initcall_funcname6 から「連続したアドレスに配置する」ので、C 言語から見たときには、__initcall6_start はあたかも関数ポインタの値を持った配列に見えるわけです。

__initcall6_start が持っている値のイメージ

static initcall_t __initcall_funcname6 = funcname;
static initcall_t __initcall_func2name6 = func2name;

initcall_t __initcall6_start[] = {
        __initcall_funcname6, 
        __initcall_func2name6, 
        ..., 
};

ただし、C 言語ではこのような書き方はできないし、仮に書けたとしても、

&__initcall6_start[0] == &__initcall_funcname6
&__initcall6_start[1] == &__initcall_func2name6

が成り立たないので、厳密に同じことはできません。

この仕組みは C 言語だけでは記述するのは恐らく不可能で、リンカとの連携の賜物と言えるでしょう。

ビルドしたバイナリを見る

論より証拠で Linux カーネルをビルドして、生成された vmlinux を readelf で調べましょう。

実験に使うカーネルは 3.14.44 で ARM Versatile PB ボード向けコンフィグでビルドしたものです。拙作の ARM9 エミュレータ ememu(emuemu についてはこちら)の動作確認用に実際に動作させていたバイナリです。

まずは -S オプションでセクションの一覧を見ます。

$ arm-linux-gnueabihf-readelf -S vmlinux

セクションヘッダ:
  [番] 名前              タイプ          アドレス Off    サイズ ES Flg Lk Inf Al
  ...
  [21] .init.pv_table    PROGBITS        c039b818 3a3818 0005cc 00   A  0   0  1
  [22] .init.data        PROGBITS        c039bde8 3a3de8 003f6c 00  WA  0   0  8
  [23] .data             PROGBITS        c03a0000 3a8000 027380 00  WA  0   0 32
  ...

アドレス c039bde8 から c039ffff まで、サイズ 3f6c 分のセクション .init.data が居ることがわかります。vmlinux をバイナリエディタなどで見る場合は Off の位置、つまり 3a3de8 を見ると .init.data のバイナリデータが見られます。

Linux はビルドしたときに全シンボルのアドレスと、シンボル名の対応表を作成してくれます。アドレスとシンボル名の対応は System.map というファイルに出力されます。

$ grep initcall6 System.map
c039fb08 T __initcall6_start

$ grep initcall7 System.map
c039fc94 T __initcall7_start
c039fcb4 t __initcall_deferred_probe_initcall7

System.map を見てもわかるように、__initcallx_start の軍団は .init.data セクションの範囲内に全員収まっていることがわかります。

初期化順序

残りの疑問である initcall6 内の呼び出し順はどうなるか?については、コンパイルされた順番になるようです。

System.map の __initcall6_start 付近を見ると、

c039fb08 T __initcall6_start
★★★arch/arm/ 以下
c039fb08 t __initcall_fpe_init6

★★★kernel/ 以下
c039fb0c t __initcall_proc_execdomains_init6
c039fb10 t __initcall_ioresources_init6
...
c039fb50 t __initcall_pid_namespaces_init6
c039fb54 t __initcall_utsname_sysctl_init6

★★★mm/ 以下
c039fb58 t __initcall_init_per_zone_wmark_min6
c039fb5c t __initcall_kswapd_init6
...
c039fb70 t __initcall_slab_proc_init6
c039fb74 t __initcall_cpucache_init6

★★★fs/ 以下
c039fb78 t __initcall_fcntl_init6
c039fb7c t __initcall_proc_filesystems_init6
...
c039fbbc t __initcall_init_jffs2_fs6
c039fbc0 t __initcall_init_romfs_fs6

★★★ipc/ 以下
c039fbc4 t __initcall_ipc_init6
c039fbc8 t __initcall_ipc_sysctl_init6

★★★crypto/ 以下
c039fbcc t __initcall_crypto_algapi_init6
c039fbd0 t __initcall_aes_init6

★★★block/ 以下
c039fbd4 t __initcall_proc_genhd_init6
c039fbd8 t __initcall_bsg_init6
c039fbdc t __initcall_noop_init6
c039fbe0 t __initcall_deadline_init6
c039fbe4 t __initcall_cfq_init6

★★★drivers/ 以下
c039fbe8 t __initcall_pl061_gpio_init6
c039fbec t __initcall_fb_console_init6
...
c039fc68 t __initcall_ms_driver_init6  -> module_hid_driver が生成した関数
c039fc6c t __initcall_mr_driver_init6  -> module_hid_driver が生成した関数

★★★net/ 以下
c039fc70 t __initcall_sock_diag_init6
c039fc74 t __initcall_flow_cache_init_global6
...
c039fc90 t __initcall_packet_init6
c039fc94 T __initcall7_start

このようになっています。linux/Makefile を見てみると、

ifeq ($(KBUILD_EXTMOD),)
core-y          += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

このように同じ順で並んでいることがわかります。ざっと見た感じだと、サブディレクトリ内のモジュール達(fs, drivers の下)も同様に、Makefile に書いた順で初期化されるようです。

要するに、モジュール B がモジュール A に依存している場合、Makefile には A → B の順で書かないとなりません。逆に書いてしまうと、モジュール B が先に初期化され、未初期化のモジュール A を呼び出し、カーネルがクラッシュする悲劇が起きます。

編集者: すずき(更新: 2015年 10月 10日 15:48)

コメント一覧

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



2015年 10月 11日

ホームディレクトリの .bashrc はどこから来る?

ユーザを useradd で追加するときに -m オプションを付けると、ユーザ追加と同時に、ホームディレクトリが自動的に生成されます。

生成されたホームディレクトリを見ると、特に何もしていないのに .bashrc や .profile などが置かれています。これらのファイルはどこから来たのでしょう?

ホームディレクトリに勝手に置かれているファイル達
# useradd testuser -m

# cd /home/testuser/

# ls -la
total 12
drwxr-xr-x 2 testuser testuser  128 Oct 11 16:50 .
drwxr-xr-x 8 root     root      184 Oct 11 16:50 ..
-rw-r--r-- 1 testuser testuser  220 Dec 12  2006 .bash_logout
-rw-r--r-- 1 testuser testuser 3515 Nov 13  2014 .bashrc
-rw-r--r-- 1 testuser testuser  675 May 13  2008 .profile

答えだけ言ってしまうと、Debian の場合 /etc/skel というディレクトリが、ホームディレクトリのひな型となります。

ホームディレクトリのひな型
# ls -la /etc/skel
total 21
drwxr-xr-x   2 root root  128 May  1 05:06 .
drwxr-xr-x 173 root root 9128 Oct 11 16:50 ..
-rw-r--r--   1 root root  220 Dec 12  2006 .bash_logout
-rw-r--r--   1 root root 3515 Nov 13  2014 .bashrc
-rw-r--r--   1 root root  675 May 13  2008 .profile

Debian 以外のディストリビューションでも、ひな型となるディレクトリがあるはずなので、探してみると面白いかもしれません。

編集者: すずき(更新: 2015年 10月 11日 16:54)

コメント一覧

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



2015年 10月 12日

ニューマシン

かれこれ 5年以上が経過した Core2 Quad マシンにお別れを告げて、新しい PC を組みました。前回同様、部品だけ買って半年くらい放置してしまいましたが、今日やっと組み立て終わって、無事動いております…。

CPU 選び

前回は Intel CPU でしたので、次は AMD にしようと思ったのですが、AMD は Bulldozer 以降 CPU の性能がどうもパッとしないようで、AMD APU にすべきか AMD FX にすべきかで少し迷いました。

普段の使い方を思えば CPU の動作速度にはさほど困っていないので、とりあえず TDP が低め(50W クラス)で一番速い A10-7800 を選びました。

AMD の CPU は元々安目の価格ですし、APU を選べばグラフィックカード代まで浮きますので、非常にありがたいです。

そういえば A10-7800 を買った直後に、次世代 APU の A10-7870K が発売されましたが、悔しいので見なかったことにします…。

浮いたお金はメモリに

AMD APU のおかげで浮いたグラフィックカード代と、SSD を流用したおかげで浮いたストレージ代(※)を全てメモリにぶち込みました。おかげでメモリが 32GB 搭載のマシンになりました。

メモリだけで 34,000円くらいしました。APU が 16,000円くらいなので、大体 2倍くらいです。我ながらアホだと思いますが、欲を言えば、搭載上限まで載せたかったです…。

今回買ったマザーボードは 16GB モジュール x 4 = 64GB が搭載上限でしたが、16GB モジュールが手に入らず諦めました。そりゃまあ 16GB モジュールなんて誰が買いますか?って話ですよ。売ってないのも当然です。

一応、真面目な話もしておくと、元々 16GB は積む予定でした。というのも、前のマシン(メモリ 8GB 搭載)は、開発用の仮想マシンと、統合開発環境と、ブラウザを同時に立ち上げて、ゴチャゴチャ作業していると、ときおりメモリが足りん!とお怒りになっていたからです。

仮想マシンと統合開発環境が GB 級のメモリを使うのは、最近はもうそんなもんだよね、と思ってますが、なぜかブラウザも意外とメモリを使います。気づいたら 1GB 以上使っていることがあって油断なりません…。

(※)さすがに 5年モノの HDD だけは、いつ壊れるかわからないので入れ替えました。いつも Seagate を使っていたのですが、Seagate は Samsung の HDD 部門と合併してからというもの、あまり良い噂を聞かないので、今回は Western Digital の WD Black を選びました。

編集者: すずき(更新: 2015年 10月 13日 03:03)

コメント一覧

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



2015年 10月 14日

今日は水曜日なんて誰が決めた?

Facebook でソフトイーサ株式会社の登さんが「日付と曜日の関連に根拠法はあるのか?」というエントリを書かれていて、いつも面白いことに気づく方だなあと思いつつ、私も興味が沸いてきたので調べてみました。

適当にググってもわからなかったので、近代日本の暦の原点ともいえる、太陰暦→太陽暦の変換点から調べることにしました。

政府、太陰暦やめるってよ

かつて太陰暦を使用していた日本ですが、明治 6年 1月 1日をもって太陰暦から太陽暦に切り替え、以降現在に続くまで、太陽暦が使われています。

暦の切り替えについては、明治 5年の詔書(国立公文書館 デジタルアーカイブ - 太政類典・第二編 - 太陰暦ヲ廃止太陽暦ヲ行フ附詔書)で頒布されています。

これは太政類典という書物でして、載っている文章を読むと「明治 5年 11月 9日、第 337号」と書いてあります。しかし法律という文字はなく、詔書と書いてあります。詔書とは、天皇が公務で意思表示をすること、らしいです。

さらに読み進めると「明治六年(神武紀元 二千五百三十三年)一月一日 水曜日」という記載もあります。

日付と曜日を結びつける法律は、この詔書にあるように思われます。しかし、

  • 太政類典なる書物は何者でしょうか?
  • 詔書=法律でしょうか?
  • 法律は現在も有効でしょうか?

こんな疑問も沸いてきましたので、もう少し調べてみます。

明治初期の法律制定

国立国会図書館の明治前期法令の調べ方 1. 明治前期の法令の概要、によれば、明治時代初期(明治19年 公文式制定まで)の法律は、制定方法が定まっておらず、太政官や政府の各省から日誌という形で発令されていたようです。今から見れば考えられないフリーダム時代ですね…。

また、国立公文書館の説明によれば、

(引用)
太政類典は、慶応3年(1867)から明治14年(1881)までの太政官日記及び日誌、
公文録などから典例条規(先例・法令等)を採録・浄書し、制度、官制、官規、
儀制等19部門に分類し、年代順に編集したものです。
(引用終わり)

だそうです。ちなみに太政官 記録課 類典科の編纂とのことです。太政官はその後の内閣に相当する機関ですね。

従って、太政類典に記載の詔書は、明治初期の法律と見なして良さそうです。

それにしても国立公文書館の JPEG 画像で太政類典を読むのは辛い…見づらくて目が死にそうです…。

今も有効なのか?

明治 5年の法律が今も有効なのか…?とお思いでしょうが、国立国会図書館 日本法令索引(明治前期編)によれば、

(引用)
太陰暦ヲ廃シ太陽暦ヲ頒行ス 明治5年11月9日 太政官第337号(布)

現在も効力を有する(平成18年現在)
(引用終わり)

とのことなので、現在も有効な法律だと言えます。頒布が明治 5年(西暦 1872年)ですから、ざっと 140年以上前の法律が今も生きているわけです。何だか気が遠くなる話です。

他の書物について

ちなみに太政類典には明治 6年1月1日が水曜という表が載っていますが、別の文書である「法令全書」にはなぜか新暦の日付と曜日の対応表は載っていません国立国会図書館 デジタルコレクション 法令全書を参照)でした。

法令全書と太政類典で載っている文章の長さが違う原因は、法令全書は別紙を省略していて、太政類典は別紙まで載せているから、と推測したのですが、何がどうなったら別紙扱いなのかが全くわかりません。

国立国会図書館のサイト曰く「布告全書」には「法令全書」で省略されることが多い別紙や別冊が掲載されている、とのことなのでぜひ見たかったのですが…、
東京までマイクロフィルム見に来いやー!」(書誌情報 - 布告全書 慶応3年12月-明治18年12月
って書いてあったので、これ以上調べるのは諦めました。

結論

とりあえず、明治 6年 1月 1日(1873年 1月 1日)は水曜日(詔書には、以降 44日についても記載有り)であり、法律に定められていて、法律は現在も有効である、という結論にしておきたいと思います。

編集者: すずき(更新: 2015年 10月 15日 02:22)

コメント一覧

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



2015年 10月 18日

画像認識の可能性

「スプラトゥーン」リアルタイム画像解析ツール 「IkaLog」の裏側を読んで。

Splatoon の画面の特徴を活かした前処理、シンプルな機械学習アルゴリズム、速度で精度をカバーなど、実用レベル(認識率 97% → 99.99%)まで持っていく執念が本当にすごいです。門外漢ながら、非常にワクワクしました。

Splatoon に関しては、サーバ運営側がデータ見せるか、統計取りゃ画像認識は要らんよね?という意見はあるでしょうけど、画像認識なら、過去の動画、非ネットワークゲームの動画、果てはゲーム以外の動画も扱える汎用性が期待できます。

汎用性という視点で見ると 19 ページ目で汎用手法(OpenCV)が使い物にならなかった、とあって、画像認識は実用には遠いのか…、とも思いましたが、音声認識がほぼリアルタイムで出来るようになってきたのと同様に、画像認識も将来もっともっと良くなって、面白い未来に一役買ってくれるに違いないです。

編集者: すずき(更新: 2015年 11月 29日 04:01)

コメント一覧

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



2015年 10月 19日

山の日

当サイトのカレンダー(右側に出ているやつ)を改良して、2016年から施行の「国民の祝日に関する法律の一部を改正する法律」に対応しておきました。

こんな風に言うと小難しく聞こえますが、要は 8月11日の「山の日」を追加しただけ、です。

編集者: すずき(更新: 2015年 10月 20日 00:40)

コメント一覧

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



2015年 10月 31日

エスケープシーケンス

自作 ARM エミュレータ(リンク)の画面、制御文字がそのまま出てしまって非常に見づらいのと、BackSpace キーすら機能せず非常に使いづらいので、画面が崩壊しない程度にエスケープシーケンス対応を入れました。

趣味とはいえデタラメに作るのは気が引けたので、エスケープシーケンスの規格についてググると、ANSI X3.64 という記述をよく見かけます。ですが、肝心の規格書が見当たりません。

他にも ISO/IEC 6429 と ECMA-048 という記述も見かけますが、結局どれがメジャーなのか、良くわかりませんでした。

今回は、無料で取得できる ECMA-048 5th edition を見ながら作りましたが、きちんと作ると面倒くさそうなので、だいぶ手抜き実装です。

パラメータの解釈が適当(03/00 〜 03/09 以外は誤動作する、3個以上のパラメータは受け付けない)なのと、インタミディエイト?何それ?状態で、イジワルすると変な動きします。

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

編集者: すずき(更新: 2015年 11月 1日 02:13)

コメント一覧

  • コメントはありません。
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 2022年
open/close 2023年
open/close 過去日記について

その他の情報

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