拙訳(一部抜粋)
1.
- 粗いZCull/Hi-Zはレンダリングパフォーマンスを劇的に改善し得る要素のひとつ
- 計算とメモリアクセスの塩梅を見直して最適化をやり直す必要があった
- 計算性能は年々すごく良くなっているけど、メモリアクセス性能はそこまで向上していないため
2.
- 視点がシャドウボリュームの内部にいるか交差しているかをきちんとテストしている
- 遅くなりがちなZ-failを回避するため
- インデックスデータはCPUで生成する
- ライトボリュームの中にあるものだけをレンダリングするため
- インデックスバッファ1つに全データを
__mm_stream_si128()で書き込む
- データがフレーム中に1度きりしか使われない場合、こまめに
__clflush()でキャッシュから追い出してやれば大規模なキャッシュ汚染は回避できる- 別のスレッドから何回も使われるデータでは意味がない
__mm_stream_load_si128()はキャッシュを介さず”read combine”でデータを読み出す- ただし、write-combinedメモリでのみ有効
- これはpredictiveなので帯域ギリギリ一杯まで使ってくれる
- キャッシュ可能なメモリにデータをストリーミングするにはx86/x64では2倍の帯域が必要になる
- キャッシュラインまるまる1本分のデータをキャッシュ可能なメモリに書き込もうとするとき、メモリからキャッシュへフェッチした分が後で完全に上書きされてしまうので無駄になってしまう
3.
- アニメーション付きメッシュがフレーム中に何度もスキニングされる
- 単純に考えれば、スキニングのコストはメッシュデータの読み出しコストに隠蔽されるので、スキニング後メッシュデータで何かしたりしないならその場で計算する方が良い
- スキニングしたメッシュをメモリに書き出したりGPUにコピーしたりを一切していないからできること
- 読み出すメモリが狭まるので、その分キャッシュに残れば必要なメモリ帯域を減らせて、結果cache thrashingが減ることになる
- 単純に考えれば、スキニングのコストはメッシュデータの読み出しコストに隠蔽されるので、スキニング後メッシュデータで何かしたりしないならその場で計算する方が良い
- ステートレスだとリソース間で競合せずに並列にたくさんのコードを実行できる
4.
- キャッシュミスが起こると数百サイクルくらいかかる
- 侵入的なコンテナは、クラスサイズがキャッシュラインを超えるくらいに大きいと、キャッシュミスが起こる
- 連結リストは一見軽そうに見えるけど、ノードをたどるときにキャッシュミスが起こりがち
- 配列の方が、侵入的でなく、イテレーションが効率的で、必要なメモリが少ない、という点で優秀
- 要素の除去は配列だと高コストなので、そこが問題になったら使うかどうか検討するくらいに考える
- とはいえ、連結リストを使うかどうかを考えるより、検索性が必要なところに配列インデックスへのハッシュテーブルを使うことを考えたほうがよっぽど良い