📷️

Spresense でスピンロックとnxsemの速度比較

に公開

Spresenseでスピンロック

おい、どこのアホだよ、前回で最終回って言ったの。最終回書いたの今日だぞ。舌の根も乾かないってこういう馬鹿を言うのか。

さて、前回どこぞのクソ阿呆はこんなバカタレなことを吐き捨ててました。

nxsem は待機とか行うっぽいので、 std::atomic_integer でスピンロックにすれば別スレッドでも速度出るかもしれませんが、スレッドまとめたら速度出てしまったので確認してません。

なんかアホがほざいてますね。

というわけで、間抜けが馬鹿さらしたので調べてきました。ほんと、馬鹿だよね。

作ったもの

https://github.com/nodamushi/zenn-program/tree/main/src/spresense/message

コード

nxsem による Queue と、全く同じ構造で std::atomic_uint32_t でスピンロックする Queue を作成し、別スレッドからpush, pop する速度を比較しました。

今回測定したい速度は「ロックが基本的には起こらないと想定している」ときのメッセージやり取りの速度です。

つまり、「送信」→「受信」→「送信」→「受信」……という様にキューが基本的に詰まらないだろう状況を想定しています。

キューの数は4(カメラのバッファの最大値が3のため)としています。

また、スピンロックは同一コアで実行するとデッドロックするので、送信コアと受信コアを指定しています。

https://github.com/nodamushi/zenn-program/blob/main/src/spresense/message/src/msg/msg_main.cxx

結果

10万回のループ(最初の1回は無視してるので9万9999回)のループにかかった時間は以下。平均は出すのが面倒くさかったのでパス。

nxsem atomic
最大 1.74[s] 0.0365[s]
最小 1.32[s] 0.0320[s]

40倍近く速度差があります。

こういうのは実行順序依存もあるので、順序を逆にして実行もしましたが、あまり大きな変化はありませんでした。

「40倍ってnxsem 側はロックに入ってるかな」と想定してキューの深さを 20万 (※ループ回数10万)にして絶対にロックしないようにしたのですが、それでも結果は変わりませんでした。純粋に処理に時間がかかってるようですね。

まとめ

単純なスピンロックに比較して nxsem は40倍ぐらい遅く 十数マイクロ秒 ほどを見積もっておく必要があります。

とはいえ、 120FPS とかいう 8 ミリ秒から見ると桁違いに早いので、速度が出なかったのは別なところに原因がありそうです。

前回はCPUコアをスケジューラ任せにしてたので、もしかしたら同一コアで動いてたのかな。もしくは、特定のコアからはアクセス早いけど、別のコアからは遅いとか。

流石にこれ以上を追う気にはならないのでここまでとします。

Discussion