2023年4月30日日曜日

手書き50マス計算、タイプ50マス計算を作った

手書き50マス計算タイプ50マス計算 を公開しました。 100マス計算は 小1の最初の頃は 100マスだと厳しい、苦手な子がやると時間を猛烈に圧迫してしまう、などの欠点があるので、50マスも欲しくなってきて作りました。 数を減らしたいときは 手書きde暗算タイプde暗算 なども使えますが、量の決まったものも必要、と予想して作りました。



使い勝手の改善

既に 手書き100マス計算タイプ100マス計算 を公開しているため、開発は楽勝でした。 アプリそのものの説明なども 100マス計算を作ったときに書いた ので不要と思います。 実装を変えた部分は、主に使い勝手の改善です。 たとえば文字を書く領域を横幅 90px から 120px まで大きくしました。 理由は計算の苦手な子は文字を書く練習が不足していることも多いので、少し大きめのほうが良いと思ったからです。

あと個人的に大きな更新として、消しゴムに touch-action: none; を加えました。 これまでは touch-action: manipulation; で良いのではないかと思っていたのですが、駄目でした。 manipulation だと手書きをしている状態のまま消しゴムを触った時に iOS のコンテキストメニューが出てしまうのですが、none だと出ません。 このへんの挙動は iOS のせいでものすごい難しくて、ようやく気付けて改善できました。 手書きのアプリは基本的に manipulation ではなく none が正解そうです。

また タイプ100マス計算タイプ50マス計算 には解答を音声で聞けるボタンを付けました。 計算がまだほとんどできない状態の子にも、ある程度は対処できるようになったと思います。

高速化

他にも高速化を頑張ってみました。 結論だけ言えば 最近追加された getContext("2d") のオプション である、 willReadFrequently: true、alpha: false が一番効きます。 この 2つを追加するだけで、手元の環境では Canvas のデータ取得速度が平均 13ms → 5ms → 4ms になりました。

さらに OffscreenCanvas を使うとレンダリングを非同期化できるのですが、 willReadFrequently: true が効かないブラウザが多いので、現状では反応速度が遅くなるかもしれません (未確認)。 仮にその問題がなくても、Safari のサポートが 16.4 からで、切替しにくい機能なのでまだ使いにくいです。

最近 Tensorflow.js で安定して使えるようになった Wasm Backend は、 残念ながら CPU と速度差はほとんどありませんでした。 Wasm + SIMD にすると最初の処理時間は 300ms → 100ms くらいになり明確に改善するのですが、 以降の処理時間はどちらも平均 50ms くらいの印象です。 5ms くらい早い気はしますが、ブレが大きく正確に計測している訳ではないので、気のせいかもしれません。 しょぼ開発 PC で大差ないならほとんどすべての端末で大差ないということなので、 Wasm は大きなモデルでないとほとんど効果がないとわかりました。 Wasm Backend を使うには追加で 1.2MB くらいのモジュールをダウンロードする必要があるので、大差ないなら不要です。

あとは getImageData() をした後の、白黒変換を改良 すると高速化するかなとも思いましたが、 既に 4ms で処理できることもあって改善は感じられませんでした。 Canvas が大きい時には効果があるかもしれません。

今後高速化の可能性があるのは WebGPU です。 なぜなら処理時間 50ms のうち推論が 40ms 近くを専有しているからです。 Tensorflow.js の WebGPU はまだ動かないので、今後に期待したいところです。 ただ反復処理じゃないから厳しいかも。

0 件のコメント: