LinuxでのCombined Write
PCI Expressにおけるメモリ書き込みは、Combined Writeを使うと高速に行えます。
Write Combinedを使わないと、PCI Expressは長さ1(4ワード)のトランザクションを発行してしまうので、極めて遅くなります。
Combined Writeというのは、CPUの書き込み機構をうまく利用した方法で、複数のメモリ書き込みを1つに結合して長いパケットにして発行するやり方です。
LinuxでCombined Writeを使う方法はよくわからないのですが、デバイスドライバの中でBARの物理アドレスを仮想アドレスにマップするときに、
ioremap_wc(BARx_BaseAddr,BARx_Length);
という関数を使うと良いようです。
ioremap(BARx_BaseAddr,BARx_Length);
や
ioremap_nocache(BARx_BaseAddr,BARx_Length);
という関数を使うと通常のWriteとなってしまうようなのですが、正直なところよくわかりません。うまく切り替わってくれないことが多々あります。
![]()
では、実際に波形をみてみましょう。MITOUJTAGのロジアナ機能を使って、PCI Expressの書き込みトランザクションを見てみます。
書き込みは、
memcpy_toio(Mapped_BAR1_BaseAddr , WriteBuffer , count);
を使いました。
まずは、普通のWriteの場合です。128バイトのデータ転送を行ってみたところ、32回のトランザクションが発生して、5.45μ秒かかっています。したがって、転送速度は23MB/secとなります。
拡大してみると、先頭のワードが40000001なので、1ワードの書き込みトランザクションになっていることがわかります。これでは遅いですね。

![]()
次は、Combined Writeにした場合の波形です。先頭のワードが40000010なので64バイトの書き込みトランザクションが2回になっています。128バイトを752nsで書き込んでいるので、速度は170MB/sとなります。
圧倒的に速くなりました。
![]()
切り替えは、ioremapを使うか、ioremap_wcを使うかといった違いだけなのですが、どうやらLinuxの起動時にはWriteCombiedを使うようになっていて、関数を変えるだけでは切り替わらないようです。
rescanを行う際に、
sudo chmod 666 /sys/bus/pci/devices/0000\:04\:00.0/rescan
sudo echo 1 > /sys/bus/pci/devices/0000\:04\:00.0/rescan
のように、バスの中までrescanをすると、この機能が切り替わるようなのですが、切り替わらないときもあります。
何がトリガーとなって、ioremapとioremap_wcが切り替わるのかは、正直、よくわかりません。OSごと再起動すると切り替わることが多いように見えます。
| 固定リンク




コメント