最終勤務日でした、入門カードや会社のPCを返却してきました。在籍期間はNSITEXE(品川のオフィス)が約5年、DENSOが約1年(新橋のオフィス)でした。
DENSOは主に自動車メーカー直請け(俗に言うTier 1)で部品、電装品を作っている会社です。私はNSITEXEに入社したこともあり、DENSOとの合併後も半導体のIPを開発する部署に所属していました。正確にはハードウェアに付随するソフトウェア開発を行っていました。いわゆるBSPとかファームウェアと呼ばれる部分になるかと思います。
会社全体を見渡せばソフトだけでなく、ハード、機械設計、プラントのようなものまであって、自動車産業の裾野の広さを感じます。自分の仕事が好きに選べるかどうかは正直言って配属次第ですが、全員のワガママは叶えられません。Panasonicも同じでした、これは大企業の仕方ない一面でしょう。どうしても気に入らないなら別の部署に移籍する制度もあるみたいです。使ったことないので詳細は知らない。
企業風土は紙文化の残るやや古い日本の大企業ですが、時代の流れに乗るべく刷新を頑張っていました。やや大企業病(実務を下請けに丸投げで、社員は納期の管理しかしない)に掛かりかけている部分もありそうですが、エンジニア目線としてはものづくり会社の気風が強く、技術的にはさっき言ったとおりで幅広くて面白いと思います。あと大企業の割に経営陣との距離が近いというか、偉い人たちのフットワークが軽い感じがします。
実は辞める気はあまりなくて管理職の昇格試験も受けてました。そんななかで突然辞めたので非常に迷惑を掛けてしまいました、申し訳ない。辞める理由を聞かれましたが、嫌なことがあったわけじゃないです。むしろDENSO良い会社ですよ、転職考えている方なら受けてみてはいかがでしょう。
理由は月並みですけど年齢です。40歳過ぎてこのまま管理職になるのも良かったですし、最後にもう一回くらい何かにチャレンジするも良かったですし、とぼんやり思っていたところに、運良くチャレンジできそうなチャンスが訪れたので乗りました。一度しかない人生なのでやりたいことをやれるときにやってみようと思いました。
年齢的に数年先の保証もないベンチャー企業に行くのは迷うところでしょうけど、NSITEXE時代を思い出してベンチャーの雰囲気は結構好きだったなー、と一歩前に踏み出せました。もちろん会社が急に消滅して40半ばで無職として放り出されるリスクはあります。とはいえ最近の動向を見ていると、
労働者側から見たらリストラも会社がなくなるのも職を失うという意味では一緒です。昔と違って40半ばで無職となっても詰みではなさそうですし、その時はその時でなんとかするしかない、そのために腕を磨いておくしかないだろう……と思える環境に変わってきたことも要因の一つです。
目次: マンガ紹介
お気に入りのマンガ紹介シリーズ。最近完結した短めの作品を紹介します。
目次: Linux
開発用のLinuxマシンの画面を見るにはいろいろな手段がありますが、最近はxrdpを使っています。WindowsからもLinuxからもリモートデスクトップで接続できて、同じ画面を拝めるので便利です。以前はTigerVNCを使っていましたが、Windows版のクライアントはVNC系よりリモートデスクトップが一番出来が良いです。
Linuxからリモートデスクトップ接続するときはxfreerdpを使います。便利なんですけど、オプションが独特すぎていつも書き方を忘れます。バージョン2系とバージョン3系で若干オプションが違いますが、今回は3系を紹介します。
$ xfreerdp3 \ /d: \ /v:remotehost:3389 \ /size:1920x1080 \ /kbd:layout:0x411 \ /clipboard:direction-to:all \ /auto-reconnect-max-retries:5 ### キーボードレイアウトの一覧を確認するには $ xfreerdp3 /list:kbd
いつも使っているオプションです。意味は下記のとおりです。
確か音声も転送できたはずですが、私はLinux側の音声は無視しているので音声関係のオプションは書いていません。こんなオプションが便利だよ、と教えていただけると喜びます。
目次: PC
かれこれ10年以上(2013年3月16日の日記参照)活躍してくれたONKYO SE-U33GXV2ですが、いよいよ調子が悪くなってきたようです。しばらく放っておくと音が出なくなってしまいます。
Windows 11のアップデート直後から発生するようになったので、Windows 11のせいである可能性もゼロではありません。が、同様の不具合に言及している人が見当たらないところを見ると、USB DACが故障した可能性の方が高いでしょう。
次のUSB DACはM-AUDIO M-Track Solo(メーカーのサイト)にしました。実はしばらく前に購入していたのに使わずに積んだままでした。活躍の場ができて良かったです。
入力が2系統(XLR/6.3mmステレオコンボプラグ: マイク/Line、6.3mmステレオプラグ: ギターなど/Line)、出力が2系統(RCAプラグ: スピーカー、3.5mmミニプラグ: ヘッドフォン)あります。ありがたいですね。
ボリュームつまみは大きくて見やすく、筐体の上部に付いています。私のように目線より下(机やPC筐体の上など)に置く人には、操作しやすくて良いです。一方でラックに入れて使う人にはやや使いづらいかもしれません。
動作も問題ないですね、変なノイズやおかしな音はしません。音質は良いんじゃないでしょうか、私の耳では細かいことは良くわかりませんけども……。
目次: OpenPilot
最近はOSSの運転支援ソフトウェアOpenPilotのコードを見ています。今日はOpenPilotのプロセス間通信について調べます。
OpenPilotは複数のプロセスが共有メモリを通じてデータを送受信しています。データ送受信のモデルはPublisher/Subscriberモデルを採用していて、1つの通信チャネルについて1つだけPublisherがいてデータ送信役を担い、複数のSubscriberがいてデータ受信役を担います。Client/Serverモデルとは異なりデータはPublisherからSubscriberへの一方通行で、SubscriberからPublisherに送ることはできません。
Publisher/Subscriberの仕組みの名前が見当たらなかったので、関連するコードのディレクトリ(openpilot/cereal)からcerealと呼びます。画像用のPublisher/Subscriberの仕組みだけ特別にVisionIpc(openpilot/msgq/msgq/visionipc)と名前が付いていてcerealと実装が異なりますが、背後にあるデータ送受信の仕組みmsgq(openpilot/msgq)は共通です。
今回の着目点はmsgqですから、cerealとVisionIpcの違いは扱いません。簡単に双方ともmsgqを使う経路がある説明だけに留めます。
まずcerealです。cerealはPython用およびC++用のクラス定義を行っています。Publisher用がPubMaster、Subscriber用がSubMasterです。PythonもC++も同じクラス名で、クラス定義、実装箇所は下記のとおりです。
背後のデータ送受信の仕組みはopenpilot/msgq/msgq/msgq.ccにあります。関数がプレフィクスmsgq_から始まるので見分けやすいです。cerealのPubMaster/SubMasterからmsgqのコードに至る経路は下記のとおりです。
PubMaster::PubMaster() PubSocket::create() MSGQPubSocket::connect() msgq_new_queue() SubMaster::SubMaster() SubSocket::create() MSGQSubSocket::connect() msgq_new_queue()
次にVisionIpcのServer/Clientからmsgqのコードに至る経路は下記のとおりです。コンポーネントによって呼び出し元は違うので、例としてPublisher側はreplayのCameraServer、Subscriber側はuiのCameraWidgetからの経路を挙げます。
CameraServer::startVipcServer() VisionIpcServer::create_buffers_with_sizes() PubSocket::create() MSGQPubSocket::connect() msgq_new_queue() CameraWidget::vipcThread() VisionIpcClient::VisionIpcClient() SubSocket::create() MSGQSubSocket::connect() msgq_new_queue()
経路は多少違うもののcerealもVisionIpcも両方ともmsgqに行き着きます。ただしcerealはmsgq以外の経路(ZMQ)が選択可能で、ZMQを選択した場合は上記と異なる実行経路となります。
ファイルの共有メモリマップをお互いのプロセスから読み書きしてデータ共有します。msgq_new_queue()にて/dev/shmにあるtmpfsファイルシステム(メモリ上にファイルシステムを作る仕組み)上に1つの通信チャネルごとに1つファイルを作成します。1つのファイルをPublisherとSubscriberが共有メモリマッピングするので、お互いに同じファイルのデータが見えます。Publisherがメモリマップ経由でファイルを書き換えたらSubscriber全員に変更が見える仕組みです。
通常、ファイルの共有メモリマップに書き込んだ内容を他のプロセスに可視化するときはmsync()を呼ぶ必要があります。しかしmsgqの実装はtmpfs決め打ちというか、msync()の手間を惜しんだのか、atomicアクセスもしくはメモリバリア__sync_synchronize()だけで済ませています。うーん?これでも動くんだ……?
// openpilot/msgq_repo/msgq/msgq.cc
int msgq_msg_send(msgq_msg_t * msg, msgq_queue_t *q){
//...
//★★q->dataは共有メモリマップへのポインタ★★
char *p = q->data + write_pointer; // add base offset
//...
// Write size tag
//★★atomicアクセス★★
std::atomic<int64_t> *size_p = reinterpret_cast<std::atomic<int64_t>*>(p);
*size_p = msg->size;
// Copy data
//★★memcpy + メモリバリア★★
memcpy(p + sizeof(int64_t), msg->data, msg->size);
__sync_synchronize();
ファイル内のデータは下記のようにヘッダ領域とデータ領域の2領域からなります。各プロセスにはmsgq_queue_t構造体が確保され、ヘッダ領域とデータ領域へのポインタを保持します。
データ領域のサイズはDEFAULT_SEGMENT_SIZE(10MiB)固定です。Subscriber数の最大数はread_pointers[]などの配列長で決まります、現状だとNUM_READERS(15)固定です。なぜ16じゃなくて15なのか?理由が良くわかりません。特に理由は書いていませんでした。
// openpilot/msgq_repo/msgq/msgq.h
#define DEFAULT_SEGMENT_SIZE (10 * 1024 * 1024)
#define NUM_READERS 15
#define ALIGN(n) ((n + (8 - 1)) & -8)
struct msgq_header_t {
uint64_t num_readers;
uint64_t write_pointer;
uint64_t write_uid;
uint64_t read_pointers[NUM_READERS];
uint64_t read_valids[NUM_READERS];
uint64_t read_uids[NUM_READERS];
};
struct msgq_queue_t {
std::atomic<uint64_t> *num_readers;
std::atomic<uint64_t> *write_pointer;
std::atomic<uint64_t> *write_uid;
std::atomic<uint64_t> *read_pointers[NUM_READERS];
std::atomic<uint64_t> *read_valids[NUM_READERS];
std::atomic<uint64_t> *read_uids[NUM_READERS];
char * mmap_p;
char * data;
size_t size;
int reader_id;
uint64_t read_uid_local;
uint64_t write_uid_local;
bool read_conflate;
std::string endpoint;
};
PublisherとSubscriberが1プロセスずついるときはこんな感じです。msgq_header_tの実体は1つで、各プロセスのmsgq_queue_tがmsgq_header_tとデータ領域へのポインタを保持します。
PublisherとSubscriber間のtmpファイル共有
データ領域はPublisherが書き手、Subscriberが読み手のリングバッファとして機能します。つまりPublisherはデータ領域に送信したいデータを書いてwrite_pointerを進め、Subscriberはデータ領域からデータを読み取ってread_pointerを進めます。
目次: ゲーム
前回の振り返り(2022年5月13日の日記参照)から2年半経ちました。所持しているゲームのリストを見るとほとんど変わっていなくて、最近ゲームしてないことが良く表れてます。特に続編系は情熱をもって遊べていないですね。小規模ゲームはいくつかクリアしました。
クリアした(実績90〜100%、シナリオコンプなど)。
たくさん遊んだ(クリア条件がないor困難すぎて挑む気なし)。
未クリア(実績、シナリオクリア率が50%以下)。
ほぼ遊んでいない。
メモ: 技術系の話はFacebookから転記しておくことにした。
< | 2024 | > | ||||
<< | < | 11 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
合計:
本日: