『池上彰の宗教がわかれば世界が見える』(池上彰)
最初に, 最近のトピックや事件にからめて世界の宗教についてサーベイし, その後,
キリスト教, イスラム教, 仏教, 神道の専門家との対談をしつつそれぞれの宗教について詳しく見る.
よくできてる. 分かりにくい専門的な言葉が飛び出すと著者がちょっと待ってと平易な言葉で解説してくれる.
日本人の「無宗教」はキリスト教などの一神教に対するアンチではなく意識していないだけで深く根付いている,
他の宗教に寛容なのだ. というあたりの話は以前読んだ『日本人はなぜ無宗教なのか』(阿満利麿)でより詳しく解説されていたのですんなり入る.
個人的には「キリスト教やイスラム教の派閥は同じ神様を信じてるのになんで対立ばっかりしてるのか」という疑問が多少は解消されるかと思っていたけど,
まあ無理だなという身も蓋もない感想を持った.
「イスラム共同体は73個の分派にわかれてそのうち一つだけが正しい」というムハンマドの言葉があるらしい.
味覚異常
今月頭にえらい風邪ひいてから体調が悪い. ずっと喉が痛いのでいくつか薬を飲んでるのだけどなかなか直らない.
で, 最近やけに牛乳が苦いと思ったら飲んでる薬に味覚異常が出るとあった. へぇ.
眠たくなる薬も飲んでるので, めちゃくちゃ眠たいのだが味が変わるのは初めて.
nasmのvpsllwのバグのパッチ
昨日Xbyakに追加し忘れていた命令群を追加したときに, またnasmのバグを見つけたので報告しておいた.
レポートが段々定型文になってきてる. しかしこうもバグの割合が高いとテストとして使うにはコストが高いな. yasmだけにしようかな.
ただyasmとmasmとnasmの出力が違っててどれが正しいのか分からんというときもあったし, まだしばらくは現状維持するか(人の振りみて我が振り直せ).
Xbaykにラベルのアドレスを埋め込むputL()命令を追加
PCSX2の高速化やってるGabestさんからのご依頼.
これまでもよくバグ報告をしてくださって大変ありがたい. 今回も追加し忘れていたいくつかのAVX2命令を教えてくださった.
putL()はテーブルジャンプしたいときに使う.
こんな感じ.
// ジャンプテーブルでraxの値に応じて分岐
mov(rcx, ".jmp_table");
jmp(ptr [rcx + rax * (int)sizeof(size_t)]);
L(".label1");
mov(rax, 5);
jmp(".end");
L(".label2");
mov(rax, 8);
jmp(".end");
L(".label3");
mov(rax, 9);
jmp(".end");
L(".end");
ret();
align(8);
L(".jmp_table"); // 多分コードとは離して置いた方がよい
putL(".label1"); // .labe1のアドレスを埋め込む
putL(".label2");
putL(".label3");
putL()で指定するラベルは上のように先に定義されていてもいいし, 後で定義してもいい.
Xbyak::AutoGrowの自動メモリ伸長モードでも使える.
先頭2行は
jmp(ptr [rcx + rax * 8 + Label(".jmp_table")]);
のように書けるとよいけど, 結構な修正が必要で当分は諦める.
現状の酷いコードをリファクタリングができたらできるようにしたいな.
『日本語の値段』(井上史雄)
世界中にある言語は, 心情的にはそれらは互いに同等の価値があると思いたい.
しかし実はれっきとした格差があるということを指摘する.
格差を学びやすさ, それを獲得したことによる利点などの市場価値の観点を用いて示す.
言語の違いだけでなく, 一つの言語でも地域による違い, たとえば戦後, 国内で方言の価値がどう変動したかに関して様々なデータが提示される. おもしろい.
ただ文章の端々に人を小馬鹿にしたようなやや上から目線の表現があるように感じられた(私の僻みな気もするが).
『ケセン語入門』というテキストで, 辞書と文法書と教科書があるらしい. ケセン語は岩手県南部の地元の言葉.
リアル『吉里吉里人』(井上ひさし)だろうな. ちょっとみてみたい.
機械学習 はじめよう 第19回 ロジスティック回帰の学習
本当だlogisticって資材の調達, 物流管理って意味なんだ. 論理学に関係がある言葉とばっかり思い込んでいた.
社内勉強会で教えもらってたっけ. 全然覚えていない…. それはともかく機会学習は計算できてなんぼのものということが分かりやすく書かれててよい.
C++Now! 2013の資料を読む会
私自身はまだC++11でコードを書いてないのだが, 最近社内でもC++11の勉強会始まったし, どんなものか参加してみた.
渋谷の乗り換えは相変わらずどこまで歩かされるのか分からず登ったり降りたりでいらいらする.
下北沢って降りるの初めてで, OpenSource Cafeというのは住宅街の中にあった.
1日1ドリンク1000円でネットワークが使える. 食べ物はあまりないのでお腹が減ると駅前まで戻って買物(持ち込み可).
資料は各自勝手に読み進める. 気になったところがあったら質問する.
最初の方は前から順に読んでいたが飽きたので途中で適当に拾い読み.
スレッドネタが多かったが重複してる内容も多い.
Richard Saunders: Thread-safe and Thread-neutral Bagsのグラフに対して
「横軸スレッド数で縦軸時間ならスケールしてるかどうかわからんだろ」というshinhさんのつっこみ.
「スレッド数増えたら速くなってるみたいだからえんちゃいますか」とか適当に答えたら「速くなるのは当たり前で」. それはごもっとも.
でもしばらく前にcygwinのマルチスレッド環境でmalloc/free使うと劇遅になって困ったりして,
という話から, tcmallocはどう? そんな感じのゆるやかな雑談.
「std::mutexのunlockって規格上は"Throws: Nothing"なのにnoexceptが付いてないのはなんでなんですかね」って質問するとcpp_akiraさんから
すかさず「事前条件が守られていないとき実装上例外を投げてもよいため」とのお答え.
なるほど. N3279(Conservative use of noexcept in the library)でごっそりnoexceptが標準ライブラリから消えていた.
処理系の話ではgccのstd::listのsize()が4.7.0, 4.7.1でO(1)になったのに4.8でO(n)に戻ったっぽい( Bug 49561 [C++0x] std::list::size complexityとか
std::stringがまだCoWの実装で規格に準拠していない, それが嫌だったらext/vstring.hを使う必要があるらしいとか.
簡単なtuple_catのサンプルがVC12では怒濤のコンパイルエラーになって悲しかった.
帰りはshinhさんとpepshisoさんと駅前でカレーを食べて帰る. よく考えたら昨日の朝も, 今日の朝も昼もカレーだった.
定期検査のため病院に行ったら, 1時間以上待ってる間に体調が悪くなって風邪をひいてしまった.
行く前は健康だったのに本末転倒だなあ.
Benchmark of Optimal Ate Pairing on Haswell(続き)
4日のベンチマークはてっきりTurboBoost enableの状態かと思っていたらdisableだった.
そして私はenableのときのrdtscの値の意味を間違えていた. w_oさんにいろいろ教えていただいた. どうもありがとうございました.
『単純な脳、複雑な「私」』(池谷裕二)
まだ最初しか読んでないけど実におもしろい. 最初に因果関係と相関関係の違いから入ってるのもよい.
サブリミナルって, 「ポップコーンの売り上げの実験で言われたけどそれは嘘だった」程度の話しか聞いたことなかったけどきちんと実験すれば効果があったことが示されているらしい(2003年の論文).
大脳基底核の淡蒼球(たんそうきゅう)という部分の活動が関わってるらしい.
そして大脳基底核は直感という能力にも関わってるそうな. へえ.
「直感」と「ひらめき」は脳内メカニズムが全く違うとかいろいろおもしろい(というかそもそも別物とは思わなかった).
「直感」はなんだかわからないけどそう思うもの, ひらめきは後から理由を説明できるものなんだそうな.
本の最後に参考文献がいろいろあげられているので機会があればみてみたい.
Benchmark of Optimal Ate Pairing on Haswell
@tanakmuraさんがベンチマークをとってbbsに張り付けてくださった.
ありがとうございます.
254bit同士のMontgomery乗算であるFp:mulがmulxなしで98clkだったのがmulxを使うと89clk.
pairingが1.32Mclkから1.17Mclkと10%ちょいの高速化. i7 2600Kが1.36Mclkだったので1命令の追加としてはかなりいい感じ.
今すぐ全マシンにmulxを入れて欲しい. mulを使うのは面倒すぎる.
あと, 私としては1割速くなるという予想があたったので満足.
w_oさんのhaswellの他の命令のベンチマークを見るとFPUの乗算もよいようだ.
期待(してない)のgather命令は予定通りinsert命令使った方が速かったそうな. orz.
Optimal Ate Pairingでmulxを使ってみる
昨日は関東GPGPU勉強会#2に参加したのだけど,
あまりに体調が悪くて途中で退出. 新宿までの道のりをふらふらと帰る. 渋谷のJR⇔東急の乗り換えも悪夢だった.
何故か行きも帰りも階段だった.
帰ったら熱が40度以上で, 悪寒がとまらない. 腰も痛い. 歯ががちがちなるというのは初めての経験だ.
今日もまだ38度前後あるのだけど, ぼーとしながらate-pairingでmulxを使ってみた.
256bit x 256bit → 512bit整数乗算はもともとmulが16回で最小だったのでmovしか減らない(Karatsubaは遅かった).
それでも36個のmovが減ったので多少は速くなってると思うのだがどうだろう.
Fp::mulが120 clkぐらいなので10clk減ると1割かな. movは実行ユニットにあまり関係なさそうだから, そこまでいかない?
どなたかHaswell持ってる方, 試してもらえるとありがたいのですが. test/bnでmulxが使えるなら使う,
test/bn -mulx 0でmulxを使わないバージョンが動作します.
Haswellのmulxを使った多倍長乗算
XbyakをHaswell対応させたので早速mulxを使ってみる. mulxは入力が二つのレジスタ(一つはrdx固定)で, 二つのレジスタに出力する.
mulx H, L, x ; [H:L] <- x * rdx
H, L, xは(64bit)汎用レジスタ. xとrdxの結果が128bitとして[H:L]になる. そして一番大事な点はフラグを一切変更しないこと.
ためしにuint64_t x[n];にuint64_t yを掛ける乗算命令を実装してみよう.
その前に準備をいくつか. 一つはmulxが使えるかどうかの判定. eax = 7, ecx = 0の状態でcpuidをみればよいらしい.
eaxだけじゃないので__cpuid()ではなく__cpuidex()を使う. gccなら__cpuid_count().
Xbyak::util::Cpu.has(tGPR2)がtrueなら使える.
新たに拡張されたVEXエンコード一般命令のうちandn, bextr, blsi, blsmk, blsr, tzcntはグループ1,
bzhi, mulx, pdep, pext, rorx, sarx, shlx, shrxはグループ2に属してるらしい.
bsfの後継のtzcntはグループ1なのにbsrの後継のlzcntは専用のフラグが割り当てられている. このあたりどういうルールかよく分からん.
もう一つは私はHaswellを持ってない. Intel Software Development Emulatorを使って試す.
残念ながら命令のCPU cycleは分からないようだ.
Xbyakのtest_util.cppサンプルで命令チェックをしてみる.
xbyak/sample>sde -- test_util.exe
64bit
vendor intel
mmx mmx2 cmov sse sse2 sse3 ssse3 sse41 sse42 popcnt aesni rdtscp osxsave
(xgetvb) pclmulqdq avx fma avx2 gpr-group1 gpr-group2 lzcnt
popcnt ok
family=6, model=C, stepping=1, extFamily=0, extModel=3
display:family=6, model=3C
エミュレータ上ではfma, avx2, gpr-group1, group2, lzcntが利用可能になっている.
さて, 多倍長乗算は筆算で行う.
x3 x2 x1 x0
* y
-------------
x0*y
x1*y
x2*y
x3*y
今まではmulがフラグを変更してしまうのでx0*y, x1*yの値を求めながらadcを使って加算していくことができなかった.
仕方がないので一端全部の乗算結果をメモリに保持するか, addの回数を2倍にするか, レジスタの許す限り途中経過を保持してやるかぐらいしか手がなかった.
mulxはフラグを変更しないのでそんなことは気にしなくてよい. すばらしい(fp_generator.hpp).
void gen_raw_mulI_with_mulx(const Reg32e& pz, const Reg32e& px, const Reg64& y, const Reg64& t0, const Reg64& t1, int n)
{
mov(rdx, ptr [px]);
mulx(rax, t0, y);
mov(ptr [pz], t0);
const Reg64 *pt0 = &rax;
const Reg64 *pt1 = &t1;
for (int i = 1; i < n; i++) {
mov(rdx, ptr [px + 8 * i]);
mulx(*pt1, t0, y);
if (i == 1) {
add(*pt0, t0);
} else {
adc(*pt0, t0);
}
mov(ptr [pz + 8 * i], *pt0);
std::swap(pt0, pt1);
}
if (pt1 == &rax) mov(rax, *pt0);
adc(rax, 0);
}
このコードはn = 2ならWindowsでは
uint64_t mulI(uint64_t *pz, const uint64_t *px, uint64_t y);
mov r11,rdx // r11 = px
mov rdx,ptr [r11] // rdx = px[0]
mulx rax,r9,r8 // [rax:r9] = px[0] * y
mov ptr [rcx],r9 // pz[0] = r9
mov rdx,ptr [r11+8] // rdx = px[1]
mulx r10,r9,r8 // [r10:r9] = px[1] * y
add rax,r9
mov ptr [rcx+8],rax
mov rax,r10
adc rax,0
ret
n = 3なら
mov r11,rdx
mov rdx,ptr [r11]
mulx rax,r9,r8
mov ptr [rcx],r9
mov rdx,ptr [r11+8]
mulx r10,r9,r8
add rax,r9
mov ptr [rcx+8],rax
mov rdx,ptr [r11+10h]
mulx rax,r9,r8
adc r10,r9
mov ptr [rcx+10h],r10
adc rax,0
ret
というコードを生成する. テストは通ってるので正しく動作しているようだ.
早く速度比較をしたいなあ.