ConiのネイティブFloat32配列のためのハードコア・カオステスト
ブラウザで高性能なアプリケーションを構築する場合、JavaScriptの汎用的なNumber型では不十分なことがよくあります。連続した生のメモリ配列が必要になるのです。Coni WASMでは、最も数学的に集約的なアプリケーションのために、ネイティブなWebAssemblyのfloat32配列に大きく依存しています。
Float32は実際にConiのどこで使われているのか?
ネイティブのfloat32配列(make-float32-array、f32-set!、f32-get)は、Coniのパフォーマンス・レイヤーの絶対的なバックボーンです。これらは以下のような機能を駆動しています:
- WebGLジオメトリ:
deep-focus-webglアプリでは、float32配列を使用して80,000頂点のブレイン・マトリックス(240,000個の浮点数!)をネイティブに数学的に形成し、その後js/float32-bufferを介して一撃でGPUに転送します。 - ゲームエンジンのパーティクルシステム:
flappy-birdやneon-boidsのようなゲームでは、並行するfloat32配列が数千のX/Y座標、速度、寿命を、ガベージコレクションの停止を発生させることなく追跡します。 - 生(Raw)のDSPオーディオ: 私たちの
sound-nodesシンセサイザーは、複雑なインパルス応答とノイズ波形をWebAudioチャンネルにマッピングする前に、float32配列を使用してネイティブに計算します。
バグ:型強制とf64.reinterpret_i64
これらの配列は非常に重要であるため、そこでのバグは壊滅的です。最近、正確な整数(例えば150)をf32-set!に渡すと、なぜか0.0が返ってくるという問題を発見しました。
何が起きていたのでしょうか?以前のバージョンのWASMコンパイラでは、整数を浮動小数点数のセッターに渡すと、コンパイラがビットを解釈するために誤ってf64.reinterpret_i64を使用し、基礎となる値を完全に文字化けさせていたのです。
解決策:Float32カオステスト
私たちはコンパイラにパッチを当て、メモリへの挿入前に整数を正しく浮動小数点数に強制(コアーション)するようにしましたが、二度と退行(リグレッション)しないという保証が欲しかったのです。そこでカオステストの登場です。
新しいfloat32_coercion_test.coniスイートに、ハードコアなカオステストを構築しました。少数のハッピーパス(正常系)の数値をテストするだけでなく、巨大な配列を割り当て、決定論的な擬似ランダムループでそれを激しく叩きます。
(deftest test-f32-chaos
"float32配列の境界と型強制のためのハードコアなカオステスト"
(let [size 1000
arr (make-float32-array size)]
(loop [i 0]
(if (< i size)
(let [
;; 極端なエッジケースを混ぜて生成:
val (if (= (mod i 4) 0) (- 0 i) ;; 負の整数
(if (= (mod i 4) 1) (* i 10000) ;; 大きな正の整数
(if (= (mod i 4) 2) (+ i 0.5) ;; 正確なfloat32の分数
0))) ;; ゼロ(整数)
]
(f32-set! arr i val)
(recur (+ i 1)))
nil))
;; ... 検証ループ ...
極端な正の整数、負の境界値、純粋なゼロ、そして小数部を持つ浮動小数点数の残酷なミックスを意図的に1,000回f32-set!関数に投げつけることで、WASMのトラップを回避し、型強制が防弾(完璧)であることを保証します。
オーバーヘッドなしでGPUアクセラレーション・アプリケーションや複雑なステートマシンを構築したい場合、メモリプリミティブに対する絶対的な信頼が必要です。カオステストにより、Coniのfloat32配列は今や実戦で鍛え上げられたものとなりました!