Microsoft Edge の機能を調べてみた - SIMD.js 編
SIMD.js は Intel, Google, Mozilla が開発、他も取り組み始めている模様で、知る限りでは Dart から SIMD を操作するやつが祖先のような気がします。(違ってたらごめんなさい)
SIMD.js は ECMAScript 2016 で計画されており、現状では通常の状態の Edge で SIMD.js は動作しません。
アドレスバーに about:flags を入力して "asm.js を有効にする" にチェックし Edge を再起動しましょう。
また、ここ最近でつくられたものですので、今後大幅な仕様変更が行われる可能性もあり、注意が必要です。
SIMD とは?
Single Instruction Multiple Data の略で、所謂、ベクトル演算(ベクトル処理)
1つの命令で同時に複数のデータに適応して並列処理する方式です。
JavaScript など通常の処理では SISD(Single Instruction Single Data)という1つのデータに対して1つの命令を処理する形をとっています。
チップによって名称や機能が異なり、たぶんブラウザがメインで使うのはこの2つ。
現在販売されているものでは問題がないと思われますが古いモバイル端末では NEON を使うことができません。
SIMD の使い道
複数のデータ群(レーン)を1度に処理できるため画像処理、音の処理、3DCG などに使われます。
概要
SIMD.js は複数の値を保持するレーンというものがあります。
JavaScript で4つ値を持つの行列を足すには4回処理する必要がありますが、SIMD の場合1回で処理することができます。
仕様では 128 bit SIMD レジスタとなっており、5つの型と2~16個のまとめたレーンをつくることができますが、
Edge で使用できるものは Int32x4、Float32x4、Float64x2 です
SIMD.Int32x4 128 Bit を4分割した 32 Bit の int 型の値を4つもつレーン
SIMD.Float32x4 128 Bit を4分割した 32 Bit の float 型の値を4つもつレーン
SIMD.Float64x2 128 Bit を2分割した 64 Bit の float 型の値を2つもつレーン
サンプルコード
注意点
以下3つ。
- new 演算子は使えませんので SIMD.Int32x4(1,2,3,0) などの前に new をつけるとエラーになります。
- 数値の演算ですので文字列関連の処理はできません。
- SIMD 命令すべてが使えるわけではありません。
使用できるメソッド
MDN とほぼ同じで日本語化されているため、あるものはリンクでのご紹介。
%type% は現状の Edge では Int32x4、Float32x4、Float64x2 のいずれかが入ります。
SIMD.%type%.zero()
レーンの値すべてに0の値を入れる
SIMD.%type%.splat()
レーンの値すべてを指定された値で設定する
SIMD.%type%.bool()
レーンの各値に bool 値を設定する。
現状の Edge は Int32x4 以外でエラーになる。
(bool なので float 使う必要がない)
算術演算
SIMD.%type%.abs() 絶対値
SIMD.%type%.add() 加算
SIMD.%type%.div() 除算
SIMD.%type%.mul() 乗算
SIMD.%type%.neg() 符号反転
SIMD.%type%.sub() 減算
SIMD.%type%.sqrt() 平方根
リンク切れ
SIMD.%type%.reciprocal() 1/x の SIMD 版。端数が出るので Float のみ
SIMD.%type%.reciprocalSqrt() Math.sqrt(1/x) の SIMD 版。端数が出るので Float のみ
シャッフル
SIMD.%type%.shuffle()
【検証できず】レーンの値を指定し、キーとなる数字で並べ替えたレーンをつくる。
恐らく Firefox の Swizzle と同じ動きをするはず。
SIMD.%type%.shuffleMix()
【検証できず】 2つのレーンの値を指定し、キーとなる数字で並べ替えたレーンをつくる。
恐らく Firefox の Shuffle と同じ動きをするはず。
現状 shuffle と shuffleMix 正常なふるまいをしない。
自分の書き方が悪いのか、バグなのか不明だが 2 つ目で実行が止まってしまっているような気がしている。
最小値・最大値、クランプ
SIMD.%type%.max()
2つのレーンの各値を比較して最大値を入れたレーンをつくる
2つのレーンの各値を比較して最小値を入れたレーンをつくる
SIMD.%type%.clamp()
レーンの値を上限と下限の値に収めたレーンをつくる
選択
SIMD.%type%.select()
選択マスク用のレーンをつくり2つレーンの値のどちらかを選択する
比較
2つのレーンの値を比較し選択マスクを返す
SIMD.%type%.equal() a == b
SIMD.%type%.notEqual() a == b
SIMD.%type%.lessThan() a < b
SIMD.%type%.lessThanOrEqual() a <= b
SIMD.%type%.greaterThan() a > b
SIMD.%type%.greaterThanOrEqual() a >= b
論理値
2つのレーンの値を論理値として新しいレーンをつくる
SIMD.%type%.and() a & b
SIMD.%type%.or() a | b
SIMD.%type%.xor() a ^ b
SIMD.%type%.not() ~a
ビットシフト
ビットシフトを行いたいレーンに値分だけビットシフトする。Firefox とメソッド名が異なるので注意。
以下 a を 変更したいレーン、bits はビットシフトさせるビット数
SIMD.%type%.shiftLeft() a << bits
SIMD.%type%.shiftRightArithmetic() a >> bits
SIMD.%type%.shiftRightLogical() a >>> bits
データコンバート
他の方に変換する。
float32 から int32 へ変更する場合、値は切り捨ての模様。
SIMD.%type%.fromFloat32x4() int32x4 からの int32 float64 へ
SIMD.%type%.fromFloat32x4Bits() float32x4 からのビット単位のコピーへ
SIMD.%type%.fromFloat64x2() int64x2 からの int32 float32 へ
SIMD.%type%.fromFloat64x2Bits() float64x2 からのビット単位のコピーへ
SIMD.%type%.fromInt32x4() int32x4 からの float32 float64へ
SIMD.%type%.fromInt32x4Bits() int32x4 からのビット単位のコピーへ
Edge では現状使えないもの
SIMD.%type%.check()
SIMD.%type%.extractLane()
SIMD.%type%.replaceLane()
SIMD.%type%.load()
SIMD.%type%.store()
SIMD.%type%.maxNum()
SIMD.%type%.minNum()
SIMD.%type%.selectBits()
SIMD.%type%.fromInt16x8Bits()
SIMD.%type%.fromInt8x16Bits()
Polyfill
一応ある
Windows 10 Moblie での対応
不明。
Lumia 1520 - Insider Preview Build 10166 で 試したところ、SIMD をオンにしない方が速くなった。
現状は最適化されていないのか、使えないのかは不明。
もっと知りたい。
英語ですが以下のサイトでどぞ
解説
仕様