普段、家の PC のパワー不足を感じることはないのですが、linux-next のクロスコンパイルをしていると、vmlinux のリンクが遅いな〜……と感じることが増えました。
比較対象は前の会社のマシンや、今の会社のマシン(割と最近の Core i5 か Core i7 が多い)です。1〜2年しか経ってない Core i7(Skylake, Kabylake 世代)と 4年落ちの AMD A10(Kaveri 世代)を比べれば遅いのは当然ですね。
新しい CPU は Intel にしようかとも思ったのですが、ニュースを見ていると Ryzen 系も大変良さそうだったので、思い切って第 2世代 Ryzen に買い替えることにしました。
AMD Ryzen 7 2700 が届きました。3年ほど頑張ってくれた AMD A10 と入れ替えました。今までお疲れさまでした。
メモリは平凡に G.Skill の AMD 向けと銘打っている DDR4-2400 2枚差し 16GB x 2 にしました。ここ数年、メモリはハズレばかりで嫌になったので、4枚差しや極端なオーバークロックメモリは避けました。
マザーボードは ASUS B450-F GAMING にしました。チップセットはミドルエンド向けの B450 です。もしハイエンド向けが良ければ X470 ですが、マルチ GPU 構成にしたい人以外、ほぼ用事がないと思います。値段の差は 5000〜10000円くらいのようです。
マザーボードは GAMING の名の通りゲーマー仕様(?)で、無駄に LED が光っていていたり、妙なプレートが付いていたり、変テコなデザインです。まあ、筐体の蓋を閉めれば光はほとんど見えませんから、気にならないでしょう……。
SSD は Samsung 970 EVO M.2 にしました。元々 Blu-ray ドライブ、HDD、SSD しか差さっておらず、スカスカだった SATA ポートがさらに寂しくなります。
SSD はかなりややこしいことになっていて、コネクタの物理形状の規格、インタフェース信号の規格、コントローラのプロトコルの規格が、複数種類存在しています。
コネクタ | インタフェース | コントローラ | 特徴 |
---|---|---|---|
SATA コネクタ | SATA | AHCI | HDD のような形、大抵は 2.5 inch |
M.2 スロット | SATA | AHCI | M.2 SSD の B Key(12-19 ピンが欠けている) |
M.2 スロット | PCI Express | AHCI | 私は見たことがない、M Key になっているはず |
M.2 スロット | PCI Express | NVMe | M.2 SSD の M Key(59-66 ピンが欠けている) |
PCI Express スロット | PCI Express | NVMe | グラフィックカードのような形 |
今まで私が使っていた OCZ Vertex は 1番目、今回購入した Samsung EVO 970 M.2 NVMe は 4番目の組み合わせに対応した製品です。2番目、4番目に両対応の製品もあるようです(B & M Key と呼ばれ、端子に切り欠きが 2つある)。
M.2 NVMe SSD は、SATA ポートやドライブスロットを占有せず省スペースで、速度も有利(NVMe を使えれば)です。ただ欠点もあって、PC の買い替えなどでデータ移行するとき、やや面倒です。
SATA 接続の SSD の場合、古い PC から取り外して新しい PC に繋げばコピーできます。今の時代 SATA ポートが 1つもないマザーボードはないでしょう。SATA から USB に変換するツールもたくさん売っています。
M.2 接続の SSD の場合、マザーボードの仕様により M.2 スロットの有無が異なりますので、もし新しい PC に M.2 スロットがない場合、データ移行が難しくなります。
次の買い替えを考えると M.2 → USB 変換機器(特に PCIe NVMe 対応のもの)を買っておきたいところです。調べてみると JMicron JMS583 という PCI Express と USB 3.0 のブリッジチップを搭載した変換ツールがいくつか発売されていました。買っておこうかなあ。
メモ: 技術系の話は Facebook から転記しておくことにした。大幅に加筆した。
いつものように linux-next を最新版に rebase したら、ROCK64 が起動しなくなってしまいました。起動時に恐ろしい量のエラーが出て panic します。エラーメッセージを斜め読みすると DMAC と SPI のエラーに見えたので、無効化してみましたが、今度は eMMC が死んで rootfs が読めずやっぱり panic します。これはダメだ。
調べてみると、DMA 関連のパッチ(LKML へのリンク)が原因でした。ML の議論を見ると、原因も判明しているようですし、そのうち linux-next も直るでしょう(後日談: 次の日に直っていました)。
今回初めてまともに linux-next を git bisect しましたが、git bisect good もしくは bad を打つ度に、ほぼ毎回フルビルドになってしまい、とにかくビルドの時間が掛かって辛かったです。
先日 Ryzen 7 に CPU を換装していなかったら、間違いなく途中で諦めていたと思います……。
メモ: 技術系の話は Facebook から転記しておくことにした。
ASUS Tinker Board を買いました。RK3288 搭載のボードです。RK3288 は 2014年に登場した 32bit CPU(Cortex-A17 x 4)な SoC です。今となっては少し古く感じます。
今あえて Tinker Board を買った理由は、私が linux-next に入れた変更(2018年 11月 10日の日記参照)で RK3288 搭載の ASUS Chromebook C201 がデグレしたらしく、再現環境が欲しかったからです。
パッチに対し、海外の方からの指摘が来ており、症状としては DMAC のコードのどこかでカーネルが吹き飛んでしまうとのことですが、手元の ROCK64(RK3328)では再現しません。
Chromebook C201 を買うのが一番良いんですが、5万円近くしますし、買っても使う予定がないので、あまり買いたくありませんでした…。
対して Tinker Board なら 1万円しませんし、同じ RK3288 搭載ですし、症状が再現しないかなあ、なんてことを期待しています。
今は Debian を起動しただけで特に何も触っていませんが、週末辺りにでもカーネル入れ替えにトライしてみようと思います。
メモ: 技術系の話は Facebook から転記しておくことにした。
Ryzen 7 は 8コア 16スレッド CPU ですが、5万円もしません。10万円あれば、Ryzen 7 2700, 32GB DDR4, NVMe SSD, マザーボードを買ってもお釣りが来てしまいます。
これほどお安く 16並列ビルド(make -j16)に耐えうる CPU, I/O, メモリが購入できる時代が来るとは思いませんでした。一昔前なら、サーバー用の異常に高価なシステムでしか実現できなかったことです。
技術の進歩って素晴らしいですね。
メモ: 技術系の話は Facebook から転記しておくことにした。
私は、比較的 PC と出会った時期は遅い(※)ので、パソコン原始時代をほとんど知らないですが、それでも当時のマシンと、今使っている Ryzen 7 マシンを比べると隔世の感があります。
(※)初めて触ったのは中学校にあった PC9821-Cb2、買ったのは PC9821-V7 で CPU は Pentium/75MHz だった、はず。
中学生で思い出しましたが、About ページの写真(Facebook のアイコンでもある)は中学 2年生の時の顔です。現像した写真のスキャンではなく、当時珍しかった「デジカメ」で撮った写真です。機種は覚えていませんが、フロッピーに記録するタイプでした。
当時とそんなに顔は変わっていませんが、髪はかなり白くなりました。何でだろ、体質なのかな……?
メモ: 技術系の話は Facebook から転記しておくことにした。
先日購入(2018年 12月 5日の日記参照)した Tinker Board で linux-next を動かしてみたら、特に何も引っかかることなく起動しました。素敵。しかし調子に乗ってコンフィグをガチャガチャ弄ってたら起動しなくなってしまいました。
ちょっと焦りましたが、同時に ROCK64 も起動しなくなっていたので、原因はコンフィグじゃなくて、linux-next の 12月 11日版を引っ張ってきたことのようです。先週もなってたなあ。またか〜。
AArch32 と AArch64 のビルドを往復でやっていて、vmlinux のリンク速度が全然違うことに気づきました。AArch64 の方が桁違いに遅いです。
AArch32 だと vmlinux のサイズは 20MB くらいですが、AArch64 向けにビルドするとなぜか vmlinux が 300MB とかになります。なぜこんなにデカいんでしょう。リンクが遅くて辛いです。
Tinker Board は U-boot で saveenv すると二度と起動しなくなります。linux-next を起動するコマンドを save したかったのですが、できません。ちょっと不便です。
この症状 ROCK64 も同じでした。Rockchip の U-boot は何かおかしいんだろうか……?
メモ: 技術系の話は Facebook から転記しておくことにした。少し加筆。
Tinker Board でサウンド周りを有効にして linux-next を動かしてみたものの、指摘された不具合(2018年 12月 5日の日記参照)が出ません。
メールでは DMA ドライバのどこかでクラッシュした、と言われました。サウンド周りのハードウェアは I2S とコーデックが居ますが、DMA を使うのは I2S だけです。コーデック max98090 は SoC 外部に居ますから、SoC 内部の DMA を使う術がありません。
I2S が原因ならば、SoC 内部のハードウェア起因ですから、Tinker Board だろうが Chromebook C201 だろうが、ボードに関わらず現象が再現しても良さそうなのに。
Chromebook で使われているグルードライバ rockchip-snd-max98090 の影響も疑って、Chromebook C201 のデバイスツリー(rk3288-veyron-speedy.dts)からデバイスノードの設定をパクってきて、max98090 を spdif-transimtter に差し替えて(Tinker Board に max98090 は搭載されていない)、無理やり動かしてみましたが、特に何事も無く動いてしまいました。
どうやっても Chromebook C201 じゃないと再現しないのかな?良くわからないバグだ……。
ROCK64 のときはアナログオーディオ出力でも HDMI 出力でも、SoC 内蔵の I2S ハードが動作しましたが、Tinker Board はちょっと事情が違います。
Tinker Board にもアナログオーディオ端子は付いていますが、接続先は RK3288 ではなくオンボードの USB Audio(Realtek ALC4040)です。アナログオーディオのためにわざわざ専用 USB デバイスを載せるとは、豪華なボードだなあ〜。
というわけで、Tinker Board で SoC 内蔵の I2S が動くかどうか試すには、アナログオーディオ端子ではダメで、HDMI 出力じゃないと本当に動作しているかどうかわからないです。我が家にはデジタルテレビならありますが、ボードからケーブルが届かないですね。
できれば HDMI が映せて、音も出せて、ボードの隣に置いても邪魔にならないくらい小さいモニタがあるとベストですが、我が家にそんなもんは無い……。
メモ: 技術系の話は Facebook から転記しておくことにした。少し加筆した。
Raspberry Pi 対抗ボードの多くは Raspberry Pi 3 の Ethernet が遅いこと(USB 接続らしい)を引き合いに出し、ネットワークが速いことを宣伝文句にしています。
宣伝文句自体は疑っていませんが、どの程度の差があるかは知らないので、測定してみました。ちょうど Tinker Board も購入しましたし、Rockchip 同士の比較もしてみたいと思います。
測定は簡単です。受信側の PC で下記を実行します。
$ iperf3 -s -p 11111
送信側の各種ボードで下記を実行します。
$ iperf3 -c (PC の IP アドレス) -p 11111
受信側の PC の CPU は Ryzen 7 2700 で、マザーボードは ASUS B450-F GAMING です。OS は Debian GNU/Linux amd64 の Testing 版です。測定時点でのカーネルは 4.18.0-2-amd64 というバージョンになっていました。
結果だけ先に言うと Tinker Board(RK3288)の方が速いです。ROCK64(RK3328)の方が後発の SoC なのですが、Ethernet は遅いみたいですね。
ちなみに Raspberry Pi 3 は 94Mbps でした。そもそも Gigabit Ether じゃないので、比べ物になりません。
念のため各ボードの Ethernet ケーブルを入れ替えてみましたが、結果は変わりませんでした。
参考までにファイルサーバとして使っている Pentium J のマシンから、同様の計測を行ったところ 942Mbits/sec でした。
結果はこんな感じでした。
katsuhiro@linaro-alip:~$ iperf3 -c 192.168.1.2 -p 11111 Connecting to host 192.168.1.2, port 11111 [ 4] local 192.168.1.16 port 58608 connected to 192.168.1.2 port 11111 [ ID] Interval Transfer Bandwidth Retr Cwnd [ 4] 0.00-1.00 sec 113 MBytes 950 Mbits/sec 0 358 KBytes [ 4] 1.00-2.00 sec 112 MBytes 942 Mbits/sec 0 358 KBytes [ 4] 2.00-3.00 sec 112 MBytes 941 Mbits/sec 0 358 KBytes [ 4] 3.00-4.00 sec 112 MBytes 941 Mbits/sec 0 358 KBytes [ 4] 4.00-5.00 sec 112 MBytes 941 Mbits/sec 0 358 KBytes [ 4] 5.00-6.00 sec 112 MBytes 943 Mbits/sec 0 406 KBytes [ 4] 6.00-7.00 sec 112 MBytes 941 Mbits/sec 0 406 KBytes [ 4] 7.00-8.00 sec 112 MBytes 941 Mbits/sec 0 406 KBytes [ 4] 8.00-9.00 sec 112 MBytes 941 Mbits/sec 0 406 KBytes [ 4] 9.00-10.00 sec 112 MBytes 941 Mbits/sec 0 406 KBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 1.10 GBytes 942 Mbits/sec 0 sender [ 4] 0.00-10.00 sec 1.10 GBytes 942 Mbits/sec receiver iperf Done.
katsuhiro@rock64:~$ iperf3 -c 192.168.1.2 -p 11111 Connecting to host 192.168.1.2, port 11111 [ 4] local 192.168.1.102 port 54768 connected to 192.168.1.2 port 11111 [ ID] Interval Transfer Bandwidth Retr Cwnd [ 4] 0.00-1.00 sec 97.6 MBytes 819 Mbits/sec 0 356 KBytes [ 4] 1.00-2.00 sec 96.4 MBytes 808 Mbits/sec 0 395 KBytes [ 4] 2.00-3.00 sec 95.8 MBytes 804 Mbits/sec 0 395 KBytes [ 4] 3.00-4.00 sec 95.7 MBytes 803 Mbits/sec 0 395 KBytes [ 4] 4.00-5.00 sec 95.8 MBytes 803 Mbits/sec 0 395 KBytes [ 4] 5.00-6.00 sec 95.8 MBytes 804 Mbits/sec 0 395 KBytes [ 4] 6.00-7.00 sec 95.8 MBytes 804 Mbits/sec 0 395 KBytes [ 4] 7.00-8.00 sec 95.7 MBytes 803 Mbits/sec 0 395 KBytes [ 4] 8.00-9.00 sec 95.8 MBytes 804 Mbits/sec 0 395 KBytes [ 4] 9.00-10.00 sec 95.8 MBytes 803 Mbits/sec 0 395 KBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 960 MBytes 805 Mbits/sec 0 sender [ 4] 0.00-10.00 sec 958 MBytes 804 Mbits/sec receiver iperf Done.
katsuhiro@raspberrypi:~ $ iperf3 -c 192.168.1.2 -p 11111 Connecting to host 192.168.1.2, port 11111 [ 4] local 192.168.1.105 port 46476 connected to 192.168.1.2 port 11111 [ ID] Interval Transfer Bandwidth Retr Cwnd [ 4] 0.00-1.00 sec 11.3 MBytes 94.6 Mbits/sec 0 29.7 KBytes [ 4] 1.00-2.00 sec 11.2 MBytes 94.1 Mbits/sec 0 29.7 KBytes [ 4] 2.00-3.00 sec 11.2 MBytes 94.1 Mbits/sec 0 29.7 KBytes [ 4] 3.00-4.00 sec 11.2 MBytes 94.2 Mbits/sec 0 29.7 KBytes [ 4] 4.00-5.00 sec 11.2 MBytes 94.1 Mbits/sec 0 29.7 KBytes [ 4] 5.00-6.00 sec 11.2 MBytes 94.2 Mbits/sec 0 29.7 KBytes [ 4] 6.00-7.00 sec 11.2 MBytes 94.2 Mbits/sec 0 29.7 KBytes [ 4] 7.00-8.00 sec 11.2 MBytes 94.1 Mbits/sec 0 29.7 KBytes [ 4] 8.00-9.00 sec 11.2 MBytes 94.2 Mbits/sec 0 29.7 KBytes [ 4] 9.00-10.00 sec 11.2 MBytes 94.1 Mbits/sec 0 29.7 KBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 112 MBytes 94.2 Mbits/sec 0 sender [ 4] 0.00-10.00 sec 112 MBytes 94.2 Mbits/sec receiver iperf Done.
RK3328 の I2S1 で 44.1kHz 系を再生すると EINVAL エラーになってしまう問題は、I2S のマスタークロック周波数が 11289600 ではなく 11289599 などという変な値が渡されて、マスタークロックとビットクロックが整数比ではなくなることが原因でした。
エラーを無視して処理を流してみると、分周比がおかしくなります。本来 11289600 / 2822400 = 4 にならなければいけないのですが、11289599 / 2822400 = 3 になって、周波数が高めに設定されてしまい、異常に音が高くなります。
Rockchip Linux はどうやって解決しているのか見ると DIV_ROUND_CLOSEST というマクロで割り算の結果を 4 側に丸めていました。本当の原因は変な端数の値を返すクロックドライバだと思うので、この対応はちょっとイケてないですね……。
ACODEC にも 2つほど問題があって、完全には解決できていません。
問題 1つ目は、44.1kHz 系を再生すると、全く音が出なくなる症状です。これはコアのリセットで直るようです。
リセットを掛けないと、切り替え以降、何をしても全く音が出ません。しかし Rockchip Linux のコードは全くリセットを掛けておらず、なぜこれで動くのか理解できません……。
気になる点としては、リセットすることで dai_set_fmtで設定された I2S のマスタースレーブ設定が吹き飛んでしまうことです。しかし ACODEC はなぜかマスタースレーブ設定が間違っていても動いてしまいます。ハードが設定値を無視しているか、Rockchip Linux のドライバが間違っているかどちらかでしょう。真相はわかりません。
問題 2つ目は、48kHz 系 → 44.1kHz 系への切り替え時、たまに音が異常に小さくなる症状です。これは直せそうにないです。
これくらいまではわかりましたが、鳴るとき or 鳴らないときの法則が全くわからないので、これ以上追うのは厳しいです。
体感では、クロック系の切り替えが早すぎると(1秒くらい?)症状が出やすいです。何でだろう??
while :; do aplay -D hw:0,0 48k.wav ; aplay -D hw:0,0 44k.wav ; done
こんなスクリプトをグルグル回すと、44kHz 系は全く音が出ません。待ち時間が足りないのかと思い PRECHARGE の後に 500ms のウェイトを入れましたが、結果は変わらず音が出ません。。。
RK3328 の ACODEC パッチを ALSA ML に送ったところ、すんなり取り込まれました。やった。作者が自分ではないドライバを投稿したのは初めてかもしれません。それでも取り込まれるんですね。
あと 48kHz → 44.1kHz 系に切り替えたときに音が出なくなってしまう病気の応急処置パッチも取り込まれました。素早く切り替えるとやっぱり音が鳴らなくなるんですが、これ以上追う手段が無いので(2018年 12月 19日の日記参照)諦めています。できれば Rockchip の中の人に直してほしいね…。
メモ: 技術系の話は Facebook から転記しておくことにした。
RK3288 の GPLL 系のクロック周波数が、49151999 のようなおかしな値になってしまう問題も、追ってみたら意外と簡単だったのでパッチを作りました。取り込まれることを祈っておきましょう。
たぶん誰も興味が無いと思いますが、下記は RK3328 GPLL 系のクロック周波数がおかしくなる問題の詳細です。
まず ROCK64 には 24MHz の水晶が載っていて、RK3328 の XIN24M に入力されています。これが FREF になります。
PLL 周波数は仕様書(RK3328 TRM)によると、
FOUTVCO = FREF / REFDIV * (FBDIV + FRAC / 224)
と書かれています。
しかしこれはおそらく誤記で正しくは、
FOUTVCO = FREF / REFDIV * (FBDIV + FRAC / 2^24)
だと思われます。
クロックドライバの実装も後者でしたし、hdk さんに教えてもらった他の Rockchip の仕様書でも 2^24 になっていましたから、RK3328 の仕様書にある 224 は 2^24 の誤記とみて問題ないでしょう。
最終的な PLL 周波数は、
FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
となります。
REFDIV, FBDIV, POSTDIV1, POSTDIV2, FRAC に設定される値は、クロックドライバで下記のように定義されています。
//drivers/clk/rockchip/clk-rk3328.c
static struct rockchip_pll_rate_table rk3328_pll_frac_rates[] = {
/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
RK3036_PLL_RATE(1016064000, 3, 127, 1, 1, 0, 134217),
/* vco = 1016064000 */
RK3036_PLL_RATE(983040000, 24, 983, 1, 1, 0, 671088),
/* vco = 983040000 */
RK3036_PLL_RATE(491520000, 24, 983, 2, 1, 0, 671088),
/* vco = 983040000 */
RK3036_PLL_RATE(61440000, 6, 215, 7, 2, 0, 671088),
/* vco = 860156000 */
RK3036_PLL_RATE(56448000, 12, 451, 4, 4, 0, 9797894),
/* vco = 903168000 */
RK3036_PLL_RATE(40960000, 12, 409, 4, 5, 0, 10066329),
/* vco = 819200000 */
{ /* sentinel */ },
};
このコードの何がおかしいのかお見せするため、試しに先頭の行の値を使って PLL 周波数を計算してみます。PLL 周波数の目標値である rate は 1016064000 です。その他の設定値は、
です。この設定値に基づいて各設定値を計算してみると、
となってしまい、1足りない変な値になります。1足りない原因は 2項目の計算結果が 63999 になってしまうことですから、直すには frac の値を 1 増せば良いです。frac を 134218 にすると、
となって、めでたしめでたしです。
以上の解析結果に基づいて frac の値を 1増やすパッチを Linux ML に送りました。英語がイマイチで、うまく説明できず、原始人のような「これ値違う、俺直す」になってしまっていますが……。
Rockchip のアーキメンテナの Heiko さんは、コミットメッセージがあまりにもひどいと直してくれる(昔も修正されたことがある)みたいなので、そこに甘えておきます。原始人英語がそのまま取り込まれても別に構いませんし。
管理者: Katsuhiro Suzuki(katsuhiro( a t )katsuster.net)
This is Simple Diary 1.0
Copyright(C) Katsuhiro Suzuki 2006-2021.
Powered by PHP 5.2.17.
using GD bundled (2.0.34 compatible)(png support.)