http://w0.hatenablog.com/entry/20060121/p1
関連記事で出てきたが(これは自動で見つけてきてえらいと思った)消してしまった黒歴史はともかく、J ver.2 を無くしてるのがかなしいな…もしかしたらHDDどれかに残ってるかもしれないが、どうやって探したらいいかもわからん。

あと http://nano.flop.jp/log2/200706.html#2007-06-28 これの日記システムの生成プログラムもなくしている(気がする)

あと忘れてたが https://tanakmura.hatenadiary.org/ これもある。(将来なんらかの理由で移行が必要になったときに忘れないようにしよう)

http://nano.flop.jp/log/index.html

見てて思ったが、2003年からのログ残してるってえらくない?17年前やぞ。

いやでも昔見てたブログとか見て回ったけど、みんな2001年ぐらいから残してるな…

http://jkondo.hatenablog.com/archive/2001 jkondoも2001年からだし、このぐらいからブログという形でフォーマットが統一されはじめたんだろうか。(もう覚えてない)


記憶をたどって探した限りで一番ログが古いのがやねうらおさんの http://bm98.yaneu.com/rsp/loglist.html これかな…日付が99/4からしかついてないけど、少なくとも99年のログはある。

しかし https://pc.watch.impress.co.jp/docs/article/backno/98index.htm pcwatch の 96/4 に勝てるのは見つからないな。

int.main.jpのコンテンツをhttp://nano.flop.jp に移動しました

http://nano.flop.jp

flopsじゃないのか…

http://nano.flop.jp/txt/index.html 勉強会用に書いた文書はリンクしなおした。

最新のバックアップがやばいSSD(https://www.amazon.co.jp/dp/B077T9XKHM) にしか入っていない状態が続いていたのでよく考えたら危なかった。

やばいSSDはアクセスできないセクタが発生して交換したので今は使ってない。

http://int.main.jpを喪失した

更新を忘れていて契約終了しました…
このドメインはもう誰かに取得されているらしいので復元はできないです。ご愛読ありがとうございました。

僕も元から誰かが使っていた形跡のあるのを知りながら、空いていたので上書きした経緯があるので、これは因果応報ではあります。

悲しいね…データはローカルにはあるはずなのでどこか別のURLのところに置くようにします…

退職した

前回までのあらすじ : http://w0.hatenablog.com/entry/20160921/1474454159

まあ挫折しました。2年11ヶ月です。

特にどうすればよかったかとか全然わからないし無力感がある。所詮雇われ会社員のエンジニアができる事なんてたかが知れてるよねみたいなことを考えがち。

次どうするかはまだ決まっていません。少なくとも9月中は法的にも立派な無職です。15年社会人やってきて、最初の転職の時にミスって2日無職になったのを除いて、はじめて書類上もきちんと無職になります。


いまだかつてないぐらい仕事する気が起きないね…なんかもうみんな好きにすれば的な…

ただ経験的に、こういう場合って休んでても状況が改善する場合はなくて、なんか次やることをはやく見つけたほうがいい。

どうするかな…まあ今の会社では色々好き勝手にやったので、貴重な経験はできた。せっかくだし経験を生かす仕事をしたほうがいいのかなやっぱり。でも(何回も言ってるが)全然違う仕事をしたい気持ちもある。といっても私にできる仕事他にあるのか…?

まあいいや…しばらくふにゃふにゃしよ…

SVEの自動ベクタライズ

ARM SVE というベクタ拡張があるんだけど、それって公開されてるコンパイラでどのぐらい対応されるんや?という話題を見かけたので、ちょっと試してみたら良い感じだったのでついでにもう少し調べてみた。

http://d.hatena.ne.jp/w_o/20150423#1429775436

個人的には自動ベクタライザというのは信用してないんだけど、それはそれとして、ループ変換ツールとしての最適化パスの処理はまあ面白いと思ってるので。


GCCは、ビルドしてもいいけど、

https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads

ここからビルド済みバイナリが取得できるので、そちらのほうが簡単だと思う。


このGCCに、-march=armv8-a+sve -O3 を渡すと、SVEを使って自動ベクタライズしてくれるようになる。


自動ベクタライザを信用しない理由として、上のリンク先で上げてる通り、どうしても命令数がかなり膨らんでしまうというのがありますね。これは性能上のデメリットもあるんだけど、出るasmの見た目が汚なくなるから嫌という気持ちの問題も大きい。


ところが、SVE向けに自動ベクトル化で出したコードは、この命令数の膨張が無くて、見ためがスッキリしてたので好きになった。

int f(int *__restrict__ a,
      int *__restrict__ b,
      int *__restrict__ c,
      int n)
{
    for (int i=0; i<n; i++) {
        a[i] += b[i] * c[i];
    }
}

これが、

f:
.LFB0:
	.cfi_startproc
	cmp	w3, 0
	ble	.L2
	mov	x4, 0
	sxtw	x3, w3
	ptrue	p1.s, all
	whilelo	p0.s, xzr, x3
	.p2align 3
.L3:
	ld1w	z1.s, p0/z, [x0, x4, lsl 2]
	ld1w	z2.s, p0/z, [x1, x4, lsl 2]
	ld1w	z0.s, p0/z, [x2, x4, lsl 2]
	mad	z0.s, p1/m, z2.s, z1.s
	st1w	z0.s, p0, [x0, x4, lsl 2]
	incw	x4
	whilelo	p0.s, x4, x3
	bne	.L3
.L2:
	ret

vectorizeしない場合は、

f:
.LFB0:
	.cfi_startproc
	cmp	w3, 0
	ble	.L2
	mov	x4, 0
	.p2align 3
.L3:
	ldr	w6, [x0, x4, lsl 2]
	ldr	w5, [x1, x4, lsl 2]
	ldr	w7, [x2, x4, lsl 2]
	madd	w5, w5, w7, w6
	str	w5, [x0, x4, lsl 2]
	add	x4, x4, 1
	cmp	w3, w4
	bgt	.L3
.L2:
	ret

ループ前の処理が3命令増えているが、ループ中の命令数は全く同じで、関数レベルで見ても12->15 の 3命令しか増えていない。neonの場合は、これが47命令の+35命令になって、ここに貼るのも嫌なレベルだ。


一番大きいのは、ループ回数がSIMD幅で割り切れない時の端数の処理に必要なマスクをwhilelo 命令一発で作れるところだろう。

http://d.hatena.ne.jp/w_o/20160901#1472719309 に昔説明を書いたけど、実際これだけ自動ベクタライザがスッキリした命令出すのを見てかなり感動しましたね。


自動ベクタライザが出すasmは汚いという時代はもう終わったんだ。


あと

int f(int *__restrict__ a,
      int *__restrict__ b,
      int *__restrict__ c,
      int n)
{
    for (int i=0; i<n; i++) {
        if (a[i]) {
            a[i] += b[i] * c[i];
        }
    }
}

こういう条件付きストアがある場合でも

f:
.LFB0:
	.cfi_startproc
	cmp	w3, 0
	ble	.L2
	mov	x4, 0
	sxtw	x3, w3
	ptrue	p2.s, all
	whilelo	p1.s, xzr, x3
	.p2align 3
.L3:
	ld1w	z1.s, p1/z, [x0, x4, lsl 2]
	cmpne	p0.s, p2/z, z1.s, #0
	and	p0.b, p0/z, p0.b, p1.b
	ld1w	z0.s, p0/z, [x1, x4, lsl 2]
	ld1w	z2.s, p0/z, [x2, x4, lsl 2]
	mad	z0.s, p2/m, z2.s, z1.s
	st1w	z0.s, p0, [x0, x4, lsl 2]
	incw	x4
	whilelo	p1.s, x4, x3
	bne	.L3
.L2:
	ret

スッキリしていて美しいですね。(でも条件付きストアはよく考えたらAVX512でも同じことになるのでSVE固有ではない)


で、まあそれはよくて、この whilelo みたいなほぼアーキ固有みたいな命令をGCCがどう扱ってるのか気になったので調べたくなった。


まあこれが富士通コンパイラなら、なんか色々追加したんだろうな、という気持ちになるけど、GCCだとあんまりアーキ固有ベッタリな変換パスがベクタライザに入ってるイメージがないので。


調べた結果としては、以下のとおりだった。

自分で調べる人は、 gcc-8.3で、-fdump-tree-all して、xx.c.161t.vect とかを見れば、色々調べられると思う。あとは -fopt-info-vec-missed の出力も参考になるかもしれない。

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/internal-fn.def;h=4080e1698ea82404a1102ef586cce64100033e76;hb=4ac50a4913ed81cc83a8baf865e49a2c62a5fe5d#l136

WHILE_ULT という whilelo と対応するtree nodeが生まれている。これはまんまwhileloで、ループ最大値とループカウンタを受け取って、それをもとにマスクを作る。


あとMASK_LOAD,MASK_STOREもある。

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/internal-fn.def;h=4080e1698ea82404a1102ef586cce64100033e76;hb=4ac50a4913ed81cc83a8baf865e49a2c62a5fe5d#l118

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/internal-fn.def;h=4080e1698ea82404a1102ef586cce64100033e76;hb=4ac50a4913ed81cc83a8baf865e49a2c62a5fe5d#l131

AVX512 用に自動ベクトル化した場合もMASK_LOAD、MASK_STOREを使うようだ。


https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/tree-vect-loop.c;h=c74a485cc2f638c26498ac6edb57faa221f5a46d;hb=4ac50a4913ed81cc83a8baf865e49a2c62a5fe5d#l1290

direct_internal_fn_supported_p で、バックエンドがWHILE_ULTをサポートしてるかどうか見てる。

https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/aarch64/aarch64-sve.md;h=d88553405094853ab58ba1c55cd212092a14116c;hb=4ac50a4913ed81cc83a8baf865e49a2c62a5fe5d#l1254

direct_internal_fn_supported_p は多分このmdから生成したテーブルとかで見てるんではないかな…(未確認)

それで、LOOP_VINFO_FULLY_MASKED_P が決定されてその場合は端数処理を付けないようにしてると思う。


ベクタライズのアルゴリズム自体は…みんなの宿題だゾ!

PCIe M.2 変換

なんか違和感を感じるよな。変換とは。

NVMeはプロトコルはPCIeなんだから、プロトコルは変換してない。PCIeはスロットの形も定義してるから、PCIeスロット M.2 スロット変換とでも呼ぶべきか?

まあM.2はM.2で、「M.2とは何か」みたいなのが一言で言いづらい感じはあるよな。

あと定期的に書いてる気がするが、これ系で一番好きなのは、「USBシリアル変換」で、U シリアル B シリアル変換であって、お前USBはシリアルとちゃうんか?的な的な。

真面目に考えれば、USBはちゃんとバスとして働いているのに対して、RS232Cは本当にただのシリアルなので、シリアルバス to シリアル変換と考えれば別にそれほどおかしくない気もする。