MetalはGPUへのアクセスを提供するAPIで、OpenGLより10倍速いという謳い文句で登場しました。本セッションではMetalの基礎を解説しつつ、そのグラフィックス描画性能をUIImageViewと比較してみます。
MetalのAPIを直接利用する機会がなくても、Metalはあなたのアプリの裏で暗躍しています。身近なクラスとの比較を通じて、普段我々が意識することのないGPUのレイヤで何が起きているのか、目を向けてみるきっかけになればと思います。
UIImageView vs Metal
Fusion社で働きつつフリーランスとして働いています。
Metalとタイトルにあるが、実際使っている人、予定のある人は少ないと思う
使い方より、それを通じてGPUレイヤーに目をつける話をしたい
なにをするコードかわかりますね
最終的に表示するピクセルバッファが入っている
フレームバッファという通り、1フレーム分入っている。
60フレームなら1秒に60書き込むことになる。
それをやるのが左のプロセッサーである。
2種類あって、CPUとGPUがある
CPUは早いが一度に運ぶのは苦手、GPUは早くないが、同時に処理できる
CPUは早くてなんでもできるので汎用プロセッサと言われる。
容易に使用率100%になってしまうので、GPUが得意なことはGPUにまかせていく
右のサンプル映像はモザイク処理を1秒間に60フレームやっている
GPUの一つの使われ方でした。
ではメタルはなにか
昔から似たようなものにOpenGLがあるがどう違うのか
いろんな会社のプラットフォームに対応しているし、いろんなベンダーのGPUに対応している
MetalはApple最適化で早い
描画だけですごいコード量
ラッパー作ったらいいかな?
つくった
比較
TableViewに並べて
性能差がでかいように大きな画像を使う
計測コードです
しかし勘違いに気づいた
メタルのほうがスクロールが固まる
これは間違っていた
GPUとCPU両方からアクセスできるメモリ領域
コマンドバッファ作る
GPUが処理する。それがさっきのコード
これはあくまでCPU側のコード
GPUコードも測るようにする
コマンドバッファに入れてから終わるまで待つ
僕の実装が悪いのか?
UIImageViewはそもそも早いぞ?
既にUIKitは内部にMetalを使っている
既に最新技術を使って最適化さている
自作したほうが早いというイメージを昔からやっていた人は持っているかもしれませんがもうそうではない
私のラッパーは何が悪かったでしょう
CPU、1段目がコマンドバッファを作る、2段めがそれをGPUに送る
3段目がGPU処理
時系列で
明るい色はユーザーが書いたコードの可視化、薄いのは暗黙的に行われている処理
大きい画像を読み込んでリサイズしてて
表示するテクスチャにコピー
間に時間が
フローを見直す
GPU処理完了をプロセッサがせっかく別れてるのに、待ってる。
リサイズのあとCPUに戻ってもう一回レンダリングしている
一つのコマンドバッファにまとめると
短縮できた
CPU・GPU間で余計なやり取りが発生していないか注意する必要がある。
テクスチャをキャッシュするとどうか
キャッシュはどこにおいているか意識する
こうするとCPUとGPUの共有領域にあるリソースを指す。
これはいいが、どういうのがダメかというと、
UIImageにしてしまうとCPUの領域にしてしまう。
OpenCVに渡すためにUIImageいしてたりとか、リソースを考慮しないコードはけっこううある
メタルでもスムーズになりました
UIKitは最適化されている、パフォーマンスを測る時の注意、無駄な処理はないか、リソースはどこにあるのか
そうした視点を共有させていただきました。