WalB
明日からのOpen Source Summit 2017の6/1 11:00に会社の人が発表する予定.
せっかくなので昔作ったスライドを手直しして置いた.
pkg-config
すぐ忘れるのでメモ. たとえばbls.pcというファイルを作る.
Name: bls Description: test Version: 1.0 Cflags: -I../../include Libs: -lmcl
CflagsはCFLAGS, LibsはLDFLAGSに対応. cgoの先頭に
// #cgo pkg-config: bls
と書いておくとenv PKG_CONFIG_PATH=(bls.pcのあるパス) go ...でbls.pcを参照してくれる.
『Optimized C++p』のp.68とp.69で引数がstd::stringかconst std::string&かで後者の方が遅くなった. その原因はsの出現するところで参照外しうんぬん~とあるのでそんなわけはあるまいに, とasmコードを出力させてみた. 本のコードだとstd::stringのデストラクタが発動して差異が分かりにくかったので
int remove_ctrlA(std::string s) { int a = 0; for (size_t i = 0; i < s.size(); i++) { if (s[i] >= 0x20) { a += s[i]; } } return a; }
int remove_ctrlB(const std::string& s) { int a = 0; for (size_t i = 0; i < s.size(); i++) { if (s[i] >= 0x20) { a += s[i]; } } return a; }
の二つのコードを見てみる. sの参照部分は同一なので著者の仮定が正しいならこの二つの関数のループ内で後者の方が不要な処理をしていることになる. Visual Studio 2010は持ってないので一番近いVS2012で試した. コンパイルオプションはcl /Oy /Ox /Ob2 /EHsc /GS- /Qpar /D_SECURE_SCL=0 /DNDEBUG /FAscの出力コードを成形したもの.
// remove_ctrlAの方 .LL4: cmp rdx, 16 jb .LN14 mov rax, QWORD PTR [rbx] jmp .LN15 .LN14: mov rax, rbx .LN15: cmp BYTE PTR [rax+rcx], 32 jl .LN3 cmp rdx, 16 jb .LN22 mov rax, QWORD PTR [rbx] jmp .LN23 .LN22: mov rax, rbx .LN23: movsx eax, BYTE PTR [rax+rcx] add edi, eax .LN3: inc rcx cmp rcx, r8 jb .LL4
// remove_ctrlBの方 .LL4: cmp r9, 16 jb .LN13 mov rcx, QWORD PTR [rdx] jmp .LN14 .LN13: mov rcx, rdx .LN14: cmp BYTE PTR [rcx+rax], 32 jl .LN3 cmp r9, 16 jb .LN21 mov rcx, QWORD PTR [rdx] jmp .LN22 .LN21: mov rcx, rdx .LN22: movsx ecx, BYTE PTR [rcx+rax] add r8d, ecx .LN3: inc rax cmp rax, r10 jb .LL4
レジスタの割り当ては異なるけどコード自体は同一. 多分本には載っていない呼び出し側でsを作るときに何か別の要因があったのだと思う.
それにしても思ってたより余計な処理をしてるなあ. 16と比較してるのは文字列がstd::string内部にあるかそうでないかで場合わけしてるせいのようだ(_BUF_SIZE = 16).
// msvc/.../include/xstring bool _Large_string_engaged() const { // returns whether the large string mode (allocated memory) is engaged return (this->_BUF_SIZE <= _Myres); } value_type *_Myptr() { // determine current pointer to buffer for mutable string return (_Large_string_engaged() ? _Unfancy(_Bx._Ptr) : _Bx._Buf); }
jnlマクロ
Intel icc 17でxbyakがエラーになるという指摘. 条件分岐命令のjnlがBessel関数のlong double版jnlと同名でそれがマクロで定義されていることがあるかららしい.
Special-Functionsを見ると, j0やらj1やy1とか変な名前の関数があるんだなあ. erfやlgammaとかは見たことあったけど. あ, でもBessel関数は見たことあるはずだよな. 多分そのときもなんでこんな名前つけてるのだろうと思ったはず. 忘れてるけど.
Vagrant for WalB
ブロックデバイスレベルのバックアップシステムWalBのサンプルのためにVagrantでいろいろ設定する.
CentOSとUbuntu両方で動作確認するのがなかなか面倒だった.
『プロフェッショナルSSL/TLS』読書会
今回は5章. 少しずつ進める.
Visual Studio with cmake
VS2017からは[ファイル]→[開く]→[フォルダ]でCMakeList.txtがあるフォルダを開くと自動的にcmakeに対応するらしい.
とりあえずmclを最低限動くようにした(CMakeLists.txt).
肩の痛み
少しよくなってきた気がする. 朝4時過ぎじゃなく6時ぐらいまで寝られた.
Goで関数の呼び出し回数を見る
coverを使えばよいらしい. テストのできるところで
go test -coverprofile=c.out -covermode=count . go tool cover -html=c.out -o c.html
でc.htmlができるのでブラウザで開いて該当関数の上にマウスカーソルを置くとポップアップで回数が表示される. 標準でこういうのが入ってるのすごいなあ.
Octaveでワイヤフレームの3次元グラフ
初めて使ってみた.
x=linspace(-2,2,20); y=linspace(-2,2,20); [xx,yy]=meshgrid(x,y); colormap(gray); mesh(xx,yy,xx.^2+yy.^2);
こんな感じで隠線処理されたワイヤフレームのグラフを書けた. 線を太くする場合には
h=mesh(xx,yy,xx.^2+yy.^2); set(h,"linewidth",2); set(gca, "linewidth", 2, "fontsize", 20);
こんなふうにすればよいようだ. ただ画像をPDFで保存すると微妙にゴミが入ってる.
機械振興会館での会議
帰り東京タワーがきれいだった.
ゆるい. 次回からいよいよC++のはなしかな.
リハビリ
可動域はだいぶ増えたが, 明け方の痛みはあまり変わらない. むしろリハビリの次の日は相当痛い. はやくよくならんもんかな.
C#でDLL呼び出し
固定長配列をclassにするかstructにするかいろいろ試行錯誤して悩んで結局structとrefですますことにした. unsafeも使わない(bn256.cs). メモリコピーのロスは問題になってから考えよう. これはGoの方が諦めが悪いというか, C#が割り切ってるというか. その違いがおもしろい.
classはそのインスタンスを隙間無く詰める方法が分からなかったので断念.
使う側がrefを明示的に書くのも面倒だったのでAddなどがちょっと変則的になってしまった.
Fr x; x.Add(y, z); // x = y + z
これはなんか分かりにくいなと思ったGoのGMPバインディングと同じインタフェースだ.
うーむ, なんか悔しい.
C#はoperator+()があると自動的にoperator+=()を使えるのだな. C++より洗練されている.
Goのunsafe.Pointer
メモリイメージが同一と分かっているけど別のクラスになっているものの配列があって, いちいちコピーしていたのだけどunsafe.Pointerを使えばそれは避けられるらしい.
type A struct { x [2]int } type B struct { y [2]int } v := make([]A, 10) w := *(*[]B)(unsafe.Pointer(&v))
A[0]とB[0]のポインタを出力してみて同一なのが確認できた(unsafe.go).
C#で固定長配列のポインタ
Cのstruct A { int x[4]; };の配列のポインタを受け取るCの関数void f(A *a, size_t n);をC#からアクセスしたい.
unsafeとfixedを組み合わせたら次のようにしてできた.
public const int size = 4; public struct A { public unsafe fixed uint v[size]; }; [DllImport("test.dll")] static unsafe extern void f(A* a, long n); A[] a = new A[5]; unsafe { fixed (C* p = &a[0]) { f(p, 5); } }
unsafeの中でポインタを取得するときにfixedで囲んでアドレスを渡すようだ. a[1]がきっかりsizeof(A)だけ次のポインタになっていることは確認できた.
後はこれをうまくラップすればよさそう.
『世界を変えた手紙』(キース・デブリン著 原 啓介訳)
パスカルとフェルマーがかけの計算で手紙のやりとりをして確率の計算をしたというのは小学生のときに読んだ何かの啓蒙書で見たことがあったけど, その詳細は知らなかった. カルダノも3次方程式の解の公式を公表したぐらいしか知らなかったが, 彼のエピソードもいろいろおもしろい.
この時代の著名人は数学の範囲にとどまらず哲学や物理や政治や医者などいろいろやっててすごい.
pkg-config
Command cgoを見ていたら見つけた. こんなのがあったのか. 恥ずかしながら初めて知った.
mclのgetStr, setStr
operator<<やoperator>>などまとめてリファクタリング. テストを通すまでにめちゃくちゃ時間がかかってしまった. ちょっと無駄になんでもできるインタフェースにしてしまったせいかもしれない.
でもあれもこれもと欲しくなることがあるのでしかたないかなあ.