はじめに
Linux では DMA Bufferを mmap した時に、ある条件が揃うと CPU Cache が無効になり、パフォーマンスが極端に落ちる場合があります。そこで、何故そのようなことが起こるのか説明します。少し長くなるので、次のように記事を幾つかに分けて投稿します。
- はじめに
- Cache Coherence 問題
- Cache Aliasing 問題
- Linux Kernel の Cache 問題の扱い
- Linux では Cache Coherence Hardware を持っていないとDMA Buffer をmmap する際に CPU Cache が無効になる
- Raspberry Pi の例
- RISC-V CPU の注意点
- 所感(この記事)
1〜3は、コンピューターアーキテクチャの基本的な事項を、簡単に説明したものです。すでにご存じの方は読み飛ばしてください。
4 はこれらの問題を Linux Kernel 内でどのように扱っているかを説明します。
5 がこれらの記事群の結論です。結論だけ知りたい方はここだけ読んでください。
1~7 の記事でLinux では DMA Bufferを mmap した時に、ある条件が揃うと CPU Cache が無効になるメカニズムを実際の Linux のソースコードを追いながら説明してきました。この記事では、それらを踏まえての私の個人的な所感を述べて一連の記事のまとめとしたいと思います。あくまでも個人的な意見なので、軽く聞き流していただければ幸いです。
この問題を Linux Kernel はなぜ放置しているのか?
私がまず疑問に思っているのがこれです。ここまで原因がわかっているのに、何故、Linux Kernel は対応しないのでしょう。いくつか私なりに考えたので、説明します。
筆者の無知説
これが一番可能性が高いと思います。私もそれなりに Cache に関しては詳しいつもりですが、まだ私の知らない技術的な「なにか」があって、こうせざるを得ないのかもしれません。あるいは理論上は問題ないけど、実装上に問題があるとか。はたまた、未公開のハードウェアのバグなんかがあって、わざと放置しているとかですかね。
この件に関して、詳しい方がいらっしゃれば、ぜひ教えてください。
Linux Kernel のメンテナーがいない説
『Linux で DMA Bufferを mmap した時に CPU Cacheが無効になる場合がある (Cache Coherence 問題の解決方法)』で、ハードウェアによる解決方法を説明しました。そして、Linux Kernel が扱うほとんどのコンピューターシステムでは、ハードウェアで Cache Coherence 問題を解決しています。
Cache Coherence のためのハードウェアが誕生してから数十年の月日がたちました。私のような年寄りのエンジニアにとってはこのようなハードウェアが無いのが当たり前でしたが、最近のエンジニアにとってはあるのが当たり前なのでしょう。
私は 『Kernel/VM探検隊@北陸 Part 6』 で、このハードウェアによる解決方法を洒落で「プログラマーをダメにするハードウェアのベスト3」と紹介しました。本当に便利すぎて、プログラマーが Cache の Coherence 問題に首を突っ込む必要がなくなるくらいです。
あまりにこのハードウェアが便利すぎて、Linux Kernel のメンテナーには、もうこの手の話が出来る人が少なくなってしまったのかもしれません。
わざと放置している説
これは、さらに荒唐無稽な説です。この件をわざと放置している理由は、ハードウェアの設計者に対する Linux からの圧力じゃないかという説です。つまり、「Linux をパフォーマンス良く動かしたければ、Cache の Coherence はハードウェアで解決してね」「現状はとりあえず最低限誤動作しないようにはしているけど、パフォーマンスにはペナルティがあります」とすることで、ハードウェアの設計者に対して Cache Coherence をハードウェア側で解決するように暗に促しているのではないでしょうか。あくまでも私の妄想ですが。
何故こんな荒唐無稽な説を私がここで力説しているかというと、私がそれを望んでいるからです。私も長いことエンジニアをやってきましたが、もういい加減、Cache の Coherence 問題はハードウェア側でやってくれよと、ソフトウェア側で対処するのは勘弁して欲しいと、切実に願っているからです。
現在の Linux Kernel は、ソフトウェアで解決する場合にも対応できるように、DMA Buffer を CPU がアクセスするタイミングと DEVICE がアクセスするタイミングを明確に分離しています。その目的のために『Linux で DMA Bufferを mmap した時に CPU Cacheが無効になる場合がある (Linux Kernel の Cache 問題の扱い)』で説明したように、その節目で特定の DMA Mapping API( dma_sync_single_for_cpu() とか dma_sync_single_for_device()など) が呼ばれます。
しかし、これらの API は、Cache Coherence 問題をハードウェアで解決している場合は何もしていません。これらの API は Cache Coherence 問題をソフトウェアで解決するためだけに存在します。
もし、Linux が扱う全てのコンピューターシステムが Cache Coherence 問題をハードウェアで解決するならば、DMA Mapping API はもっと簡単になります。Linux が将来的には Cache Coherence ハードウェアを持っていないコンピューターシステムのサポートを打ち切ることを視野にいれているのかもしれません(あくまでも私の妄想です)。
また、DMA Buffer を CPU がアクセスするタイミングと DEVICE がアクセスするタイミングを明確に分離するという制約は、DEVICE の設計にも影響を及ぼします。この制約によって、 DEVICE 側は自由なタイミングで DMA Buffer をアクセスすることが出来ず、ことあるごとにソフトウェア側にお伺いを立てたり、はたまた箸の上げ下ろしまでをソフトウェア側から指示される必要があるなど、結果的にこれらのオーバーヘッドが全体の高速化の足を引っ張っているんじゃないかと思っています。この点が改善されれば、もう少し良い設計が出来るんじゃないかと思っています。
参考
- 『Kernel/VM探検隊@北陸 Part 6』@connpass
https://kernelvm.connpass.com/event/297033 - 『Kernel/VM探検隊@北陸 Part 6』@YouTube
https://www.youtube.com/watch?v=fp-LZl0GIFs