2024.12.10
“放置系”なのにサイバー攻撃を監視・検知、「統合ログ管理ツール」とは 最先端のログ管理体制を実現する方法
リンクをコピー
記事をブックマーク
光成滋生氏(以下、光成):本題に戻ってWebAssemblyなのですが、レジスタは32bitと64bitのレジスタをもっています。加算は64bit+64bitで、結果は64bitになります。Carryはもっていません。乗算は32bit×32bitの64bitです。128bitに出力する命令はありません。素直なCでできる範囲しかありません。詳しい資料はここに載っています。
Carry演算をエミュレートしないといけません。どうやってやるかですが、やることはそんなに難しくありません。64bitのxとyを足して、65bitになって、そのCarryがなくなったということは、2つの足した値が足す前よりもcに小さくなっているとCarryが発生するということです。
この命令に対応するWebAssemblyのコードは、lt_uというunsignedのless thanという意味でxとyを比較してxがyより小さかったら1になる、そうでなければ0を使います。他にle (less than or equal)とかequalとか同様にsignedに対する命令や、selectという条件演算子相当の命令もあります。
64bitなので、ここでTをunit64_tとして、入力がx、y、cの時に出力をx+yとadoc相当をエミュレートしようとすると、xにCarryに足してその値が元より小さくなっていたらCarryが発生。yに足し込んで、そのあともう1回Carryを更新します。
1回の計算で、addが3回でlt_uが2回。今までのIntelの命令だと1命令でできていたのがこのぐらいかかるのでけっこうヘビーです。しかもlt_uみたいなのは多分JIT化して内部的にはcmpとかcmovとかになるのでもっと重くなります。
数年間これを使って、64bitベースで実装していたのですが、ふと32bit単位になったらどうなるのかなと思いました。32bitのxとyに対して、ゼロ拡張してから足した値を32bit右シフトします。するとこれはCarryが入ってきます。先ほどの例でいうと、xとyとcに対してxを64bit拡張してからyとcを足します。下位32bitを取り出して、上位32bitをCarryします。
32bitのCPUでCarryがない場合は同じことをしようと思っても、64bit拡張するとC言語的に内部的に同じことをするので無駄ですが、WebAssemblyは32bitのレジスタと64bitのレジスタの2つもっているので、ちょっと様子が違います。
1回の要素辺りaddが2回、シフトが1回でゼロ拡張が2回です。64bit単位でやるところを32bit単位でやると2倍の要素になります。例えば256の場合、64bitだと4つでいけたのが32bitだと8個いるので演算回数は増えます。マイクロベンチを取ってみて、もしかしたら速くなるかなと思ったんですが、微妙に64bit版のほうが速いです。
JITがどうなるかわからないので、ブレが大きいです。昔考えた時は、ここで遅くなったので諦めたのですが、もう少し考えてみました。32bit単位の場合、このCarryのcは先ほどは1bitだったのですが、32bitあるわけですね。ということは、途中のCarryをまとめて足してから操作できます。
ここは非常に複雑な話になるので、ざっくりと結果だけ言います。256bit×256bitで512bitの乗算をやって、64bit単位で実装をしてみました。64×64から128はもっていないので、32×32の64を組み合わせて実装しました。それと今回32bit単位で実装したものを比較すると、1割から2割ぐらい速くなりました。これはちょっと意外だったのですがおもしろい結果だと思っています。
最初に紹介したペアリングは、乗算がプロファイルのかなりの部分を占めるので、これだけ速くなると全体も速くなってかなり効果が大きいです。詳しい人のために紹介しておくと、Karatsuba法という、加算を増やす代わりに乗算の回数を4回から3回に減らすという方法があります。32bit単位でやるとけっこう長い範囲になるので効果があるかなと思ったのですが、WebAssemblyの実装だと加算のほうが重くなってしまうので、このぐらいのものは使わないほうが速かったです。メインは32bitでやったほうがうまくいったということです。
ここからはちょっと違う話をします。clang-11から_Extlntという機能が導入されています。これはuint128_tやuint1024_tが実装できる言語拡張で、typedef unsigned_Extlnt(256)とやるとunit256_tが作れます。しかも今までの整数のようにキャストして読み込んで、512bitにゼロ拡張して掛け算すると、これだけで256bitの乗算ができます。
今までunitしていたのはclangが生成してくれるという非常に夢のような世界が始まっています。こういう機能をC++にも入れようという提案があって、解説しているものを要約したのもあります。将来はもしかしたら入ってくるかもしれないです。
今のところ残念なところがいくつかあって、x64でベンチマークを取ってみました。clang-11-Ofastでやりました。mclは私が実装しているライブラリで、職人的にたぶん世界最速でadox、adcxを使っています。clangはmulxまでしか使わないです。なおかつレジスタスピルをやっているのでけっこう遅いです。square演算だと半分ぐらい変わってしまいます。
でも将来clangが進化したら、これぐらいになってくるのかなという気はします。WebAssemblyですが、コンパイルはできますがリンクはできない状況です。_multi3がないと言われます。これはclangを使っていてよく見ます。clang-8の頃は自分でこの_multi3を実装して、うまいこと動いていたのですが、clang-8の時に動いていたものをclang-11で使うと、function signature mismatchと出て動きませんでした。
時間がなくてこれ以上調べていないです。まあ、割と仕様がよく変わるので仕様はよくわからないです。昔は使おうとするとLLVMが落ちていたので、ここまで生なエラーにはなっていたのでだいぶ改善されています。
実際にC、C++でwasmを生成するには、emcc(Emscriten)かclangでやります。私は主にemccを使っています。理由はいくつかあって、標準ライブラリに対応していてmallocも使えます。使わないようにしているのですが、clangだとまだまだ生なコンパイラです。
関数exportする時のやり方がちょっと違ったり、名前に"_"が付く・付かないだったり。emccで便利なのは、SINGLE_FILEとやるとWebAssemblyのバイトコード、base64コードを指定して埋め込んだjsを1個にして作ってくれるのでWebPackなどで、使いやすいです。clangはLLVM IRを使えて便利ですが、ちょっとおかしいところが多いです。
まとめます。多倍長演算ではCarryの扱いが重要です。x64には便利な命令がいろいろ書かれていて、高速化に関与しています。wasmはCarryを扱う命令がないので、これは素直に記述する範囲でしかできません。あるいはCで記述して、十分高速なコードになります。それ以上速くできない感じです。clangの_Extlntに期待しています。
個人的にはemccがLLVM IRや_Extlntをサポートしたらclangに移行してみようかなと思います。発表は以上です。ありがとうございました。
司会者:ありがとうございました。では質疑に移ります。これはサイド的な質問ですが、「wasmで暗号処理するというのは、side channel攻撃に対する考慮はどれくらいすべき・しているものでしょうか?」いかがでしょうか?
光成:難しい質問ですね。スマートフォンとかでクライアントで使う時はside channelをほとんど気にしなくていいのかなという気もします。何か攻撃するツールが入っていたらやられるというのはありますが、そうなっていたらもうside channelではなくて、どのレイヤーでもヤバいことになっているので、あまりそこは気にしなくていいのかなと思います。
ただ先ほどの紹介のように、サーバーサイドでAssemblyを使う時はや多少は気にしていかないといけないかなと思います。私自身はそんなに気にしていないのですが、最初のコード生成の時に定数時間で計算するモードを追加したりは多少やています。遅くなるけれども、より安全にしたい時はそちらのモードを使って対策をしている人が多いと思います。そこは程度によるんですけどね。やればやるほど遅くなるので。
司会者:ありがとうございます。「modのpはどうしているのかが気になる」というツイートがありました。
光成:すみません。今回は足し算・掛け算の説明だけで、modは2、3倍しゃべらないといけないのでざっくり消してしまっています。別の学会でしゃべっている資料を公開しているので、資料に興味があればそちらをご覧になってください。
司会者:ありがとうございます。もう1つ「32bitごとの演算をSIMD proposalを使ってやる予定はありますか?」という質問があります。
光成:そうですね。wasmにもSIMDが入ってくるとかあるんですが、先ほど言ったようにツールがまだこなれていません。アルゴリズムのところで悩むならいいんですが、使い勝手のほうでリソースを食ってしまうのはあまり好きではないので、まだ様子見という感じです。
司会者:ありがとうございます。
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
2024.12.09
国内の有名ホテルでは、マグロ丼がなんと1杯「24,000円」 「良いものをより安く」を追いすぎた日本にとって値上げが重要な理由
2024.12.09
10点満点中7点の部下に言うべきこと 部下を育成できない上司の特徴トップ5
2024.11.29
「明日までにお願いできますか?」ちょっとカチンとくる一言 頭がいい人に見える上品な言い方に変えるコツ
2024.12.04
いつも遅刻や自慢話…自分勝手な人にイラっとした時の切り返し 不平等な関係を打開する「相手の期待」を裏切る技
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.12.06
嫌いな相手の行動が気になって仕方ない… 臨床心理士が教える、人間関係のストレスを軽くする知恵
2024.12.03
職場の同僚にイライラ…ストレスを最小限に抑える方法 臨床心理士が語る、「いい人でいなきゃ」と自分を追い込むタイプへの処方箋
2024.12.05
「今日こそやろう」と決めたのに…自己嫌悪でイライラする日々を変えるには
PR | 2024.12.04
攻撃者はVPNを狙っている ゼロトラストならランサムウェア攻撃を防げる理由と仕組み