重要なポイント:
- 非決定的なADASまたはADスタックは、エンジニアリング上の意思決定の信頼を損なう結果を生み出します。
- 決定論は先行投資です。チームが非決定的ソフトウェアの開発に費やす時間が長ければ長いほど、決定論を実現するのは難しくなります。
- 決定的コードにより、ADASとADの開発がより迅速かつ容易になります。
先進運転支援システム(ADAS)または自動運転(AD)による一時停止のない左折操作のシミュレーション中に、自車両は対向車の進路に向かって走行します。この動作は明らかに危険ですが、なぜこのようなことが起こったのでしょうか。ADASやADの開発チームはシミュレーションを何度も繰り返し実行しますが、そのたびに自車両はターンをうまくナビゲートします。
ADASとADの開発チームは、どうすれば上記のような問題を確実に再現できるのでしょうか。繰り返すことのできない問題を根本原因とし、修正するにはどうすればよいでしょうか。要するに、自社のADASやADスタックを信頼できない場合、チームは何をすべきか、ということです。
ここで決定論の出番です。
決定論とは
ソフトウェア開発における決定論とは、同じ入力が与えられれば、プログラムを何度実行しても、プログラムは同じ中間状態を通過しながら常に同じ出力を生成することを意味します。
このブログ記事では、ADASまたはADスタックが非決定的である場合に発生する可能性のある問題について説明します。仮説上の AD スタックの具体例を見て、その非決定的な動作の兆候を探り、根本原因を見つけるために考えられるアプローチを取り上げ、考えられる解決策について説明します。
ケーススタディ:新しいパーセプションモジュールのテスト
ここでは、時間情報(つまり実時間)としてシステムクロックを使用するADスタックを開発しているとします。1 回の更新にかかる予算は 10 ミリ秒です。コントロールモジュールが 10 ミリ秒以内にコマンドを生成しない場合、AD スタックは最も直近のコマンドを使用します。スタックを何千回もテストしてきましたが、特定のシナリオをシミュレートしても常に同じ出力が得られました。このことから、私たちの AD スタックは決定的であると考えるようになりました。
新しい認識モジュールを統合した後、一時停止のない左折シナリオをシミュレーションで実行します。自車両は、一時停止のない左折をしながら、対向車の進路に突入します。同じシナリオをもう一度実行しますが、今回は、自車両は対向車の進路には進みません。何が起きたのでしょうか?この非決定的シミュレーション結果の原因を特定して対処するにはどうすればよいでしょうか。
症状
同じシナリオをさらに1,000回実行します。データを見ると、次のことがわかります。
- 99% のシミュレーション実行で、結果は同じように表示されます。
- 一致しない結果の 1% 内では、一貫性がありません。時々、自車両は対向車の進路に突入しますが、シミュレーションの全く同一のタイミングでそのようにはなりません。私たちのADスタックは、異なる制御シーケンスと自車両のパスをランダムに生成しているようです。
次に、古い認識モジュールを使用して同じシナリオをさらに1,000回実行します。今回は、結果に違いは見られません。
診断
上記の症状から、新しい認識モジュールが非決定性を引き起こしていると考えられます。残念ながら、この問題の根本原因となるヒントは他にありません。幸いなことに、AD スタックのさまざまな非決定性の原因を除外するために実行できるチェックがいくつかあります。
非決定性コードの除外
コードを調べて発見できる非決定性の一般的な原因はいくつかあります。
認識モジュール・コードとそのサード・パーティー・ライブラリーを調べ、乱数ジェネレーターが非決定性の原因である可能性をすぐに除外しました。また、変数は常に正しく初期化されていることもわかっているので、未定義の動作も除外しています。
並列処理を探すと、自車両状態の更新方法に問題があることに気づきます。制御モジュールはサイクルごとに 1 回更新されることになっています。ただし、制御モジュールが 10 ミリ秒以内に新しいコマンドを生成しなかった場合、物理モデルは最も直近の制御コマンドのみを使用します。それが非決定性の原因である可能性はあるでしょうか?
コントロールモジュールの調査
AD スタック内の操作順序を理解するために、各モジュールに費やした時間と、それらの計算が行われる順序を明らかにするトレースツールを使用します。トレース出力を見ると、AD スタックの更新の中には、10 ミリ秒の予算で割り当てられている時間よりも多くの時間を必要とするものがあることがわかります。また、これらのインスタンスは非決定的な動作のインスタンスと完全に相関していることにも気付きました。
ここで問題となるのは、物理モデルが実経過時間を利用して、次の車両の状態をいつ計算するかを決定する点です。この更新を計算するときには、制御モジュールから直近に提供された制御コマンドだけを使用します。その結果、CPU 負荷が高い場合、制御モジュールは 10 ミリ秒以内に新しい制御コマンドの計算を完了せず、物理モデルはすでに存在する制御コマンドを使用して処理を進めます。そのような場合は、別の制御コマンドセットを実行すると、結局は別の自車両のパスになってしまいます。
非決定性の根本原因がわかったので、シミュレーション結果を再評価します。当初考えていたよりも、異なる動作の事例がはるかに多いことが判明しました。シミュレーション実行のほぼ半分に、ほとんど気づかない程度に少しだけ自車両のパスが変化しています。車両の挙動が大きく変化するのは、シミュレーションの決定的な瞬間に計算時間が予算内にに納まらなかった場合だけです。一時停止のない左折時の決定ポイントは、そうした重要な瞬間の1つです。自車両は実質的にほんの一瞬の間「一定状態」のフリーズになります。これは比較的短い時間ですが、重大な安全違反を引き起こすほど長い時間です。
非決定的シミュレーション結果の根本原因分析を完了したら、どうすれば問題を解決できるでしょうか?
改修
AD スタックのタイミング関連の問題に対処する方法はいくつかあります。
ハードウェアのアップグレード
私たちが直面している問題はパフォーマンスの問題であるため、より強力なコンピューターで解決できる可能性があります。このような問題への対処方法は迅速で、エンジニアの奪い合いを防ぐ最善の方法である場合もあります。もちろん、これは問題の実際の解決策ではなく、問題の症状を遅らせるための費用のかかる方法です。それでも、ハードウェアのアップグレードは、適切な解決策に投資する間、時間のプレッシャーを和らげるのに役立ちます。場合によっては、それが私たちが取ることができる公正なアプローチかもしれません。
スタックのパフォーマンス向上
あるいは、コードを最適化して実行時間を短縮することもできます。これをこれまで行ったことがなければ、すぐに実装できる簡単な修正が見つかるでしょう。ハードウェアのアップグレードと同様に、これらの最適化によって症状は解決されるかもしれませんが、問題の根本原因は解決されません。このアプローチを別の長期的な解決策と組み合わせなければ、再び非決定的な動作が見られることが予想されます。
外部時間とブロック実行を使用する
この問題を解決する唯一の方法は、AD スタックが外部クロックソースからの時間を受け入れ、モジュールがそれぞれの入力を待ってから処理を進めるようにすることです。この場合、AD スタックは、直近最後に計算されたコマンドを使用するのではなく、新しい制御コマンドを待つ必要があります。
シミュレーションの実行中に、AD スタックに制御コマンドを待たせるには、外部のタイムソースを使用する必要があります。決定論を実現するには、外部時間を使用する必要があります。外部時間を使うと、シミュレーションをいつ進めるかを制御できるからです。システムクロックに頼っていると、コードの実行が時間内に終了する保証はありません。新しい認識モジュールの例では、AD スタックは常に非決定的でした。非決定性が明らかになるのは時間の問題でした。
このソリューションは、前述の 3 つのオプションの中で最も複雑で時間がかかります。AD スタックがシステムクロックを使用する場所をすべて特定するのは難しい場合があります。また、外部クロックソースへの変更をテストするのも難しい場合があります。それでも、決定的なシミュレーション結果を保証するには、このソリューションしかありません。このソリューションを実装する最善の方法は、既存の AD スタック構造によって異なりクロック同期が必要ですが、これはこのブログ投稿の範囲外となります。
実行時のブロックは、シミュレーションなどのオフラインユースケースでのみ使用できる操作モードであることに注意してください。AD スタックを現実の世界でテストして運用する場合、実行時に特定の側面がブロックされてしまうと、確固たる安全策を講じることができません。スタックは、「決定的」な実行モードと、呼び出しがノンブロッキングの「ハードリアルタイム」モードで設計できます。これにより、現実世界での有用性を犠牲にすることなく、シミュレーション内で決定論のメリットを享受できます。
予後
現実の世界は決定的ではないのに、そもそもなぜシミュレーションの決定論を実現する努力をしなければならないのでしょうか。なぜ決定論が重要なのでしょうか?
このブログ記事で取り上げた例は、比較的簡単にデバッグでき、根本原因も調べやすいものでした。ただし、サンプルの AD スタックの相互接続性を大幅に簡略化し、ソースコードの品質についていくつかの前提を立てたため、目前の問題に気づきやすく、修正するのも簡単でした。現実世界の ADAS と AD 開発では、他にも無数の問題や矛盾する要因が物事を複雑にし、考えられる解決策に対する私たちの見方を曖昧にする可能性があります。
たとえば、そもそもADスタックが決定的に動作しなかった場合はどうなるでしょうか。エンジニアはシミュレーション結果の小さな違いを無視することに慣れているので、パフォーマンスの問題をすぐには認識できないでしょう。一時停止のない左折問題はシミュレーションの 1% 未満で発生するため、完全に見逃してしまう可能性があります。この特定のシナリオを十分な回数実行しなかったがために問題に気付かなかったらどうなるでしょうか。AD スタックには衝突を引き起こす可能性のある重大なバグが含まれていますが、仮想テストではこれらの安全上の問題が発見されない可能性があります。シミュレーションで発見できない問題はすべて実際のハードウェアで表面化します。そしてそれはテストコストが非常に高く、重大な安全上の影響も伴います。
喪失した自信
決定論がなければ、私たちのアプローチに対する大きな自信を失ってしまいます。実際、私たちが気付かないうちに、シミュレーションの結果が完全に間違っている可能性があります。シミュレーション中に、実行処理を適切にブロックせずに制御モジュールの実行速度が遅くなってしまうと、まったく収束しないか、サンプルが少なすぎて知覚を適切に追跡できなくなる可能性があります。
決定論を保証できないと仮定すると、何千ものシミュレーションを実行して結果を分析するという統計的アプローチしか取ることができません。問題が見つかった場合は、その解決策を推測し、その推測を実装してから、同じシナリオをさらに何千回も実行して、修正がうまくいったかどうかを確認できます。ロングテールのシナリオでは、このアプローチは現実的ではないことが多いです。というのも、ほんの数個のエッジケースで信頼を得るためには何百万回ものシミュレーションが必要になるからです。一方、AD スタックが決定的であれば、1 回のシミュレーションで特定のシナリオが成功することが証明されます。何百万ものシミュレーションを実行することは可能であり、今後も実行する可能性は高いですが、各シミュレーションでカバーされるシナリオは 1 つだけです。
決定論なくして、ADスタックが一時停止のない左折に対応できるかどうかがわかるでしょうか?他の交通状況、道路の大きさ、各エージェントの移動速度、または天候の観点からシーンを変えたらどうなるでしょうか。決定的スタックでは、これらのシナリオのバリエーションはそれぞれ 1 つのシミュレーションになります。決定論がなければ、おおよその信頼度を得るには、各バリエーションを数百回または数千回実行しなければならない場合があります。高品質なシナリオとシナリオバリエーションの作成について詳しくは、このブログ投稿を参照してください。
難しい開発
シミュレーションを実行するたびに同じ結果が得られないと、ソフトウェア開発ははるかに困難になります。バグを修正し、修正の前後にシミュレーションを実行したとします。2 回のシミュレーション実行の結果が異なる場合、その違いは実行した修正によるものか、それとも別の原因によるものか。スタックが決定的でなければ、確実に知る方法がなく、ソフトウェア開発者が迅速かつ自信を持って行動することが難しくなります。
一般に、クラウドでソフトウェアを開発する方が時間がかかるため、ADASとADの開発におけるこの難しさは、クラウドでシミュレーションを実行するとさらに大きくなります。我々が開発する AD のスタックでは、パフォーマンスの問題が発生したときに、このブログ記事で取り上げたような問題が発生します。また、クラウドマシンの方がローカルデスクトップよりもパフォーマンスが低下するのはよくあることです。この問題がクラウドでのみ発生する場合はどうなるでしょうか。ローカル環境と比較して、問題の根本原因を突き止めるのが難しく、修正をクラウドにデプロイするのに時間がかかるため、ソフトウェア開発者は問題の解決により多くの時間が必要になります。
汚染されたプロセス
システムのいずれかの側面が非決定的であれば、システム全体が非決定的になります。1 つの非決定的なデータがあると、すべてのダウンストリームの計算で非決定的な結果が生じます。ADAS または AD スタックでは、計算によってループが形成され、車両の新しい状態が次の反復への入力になります。つまり、すべてのモジュールが決定的でなければならず、そうでなければスタック全体が決定的になることはできません。ADASとADスタックの性能をテストするために使用するシミュレーション・ツールでさえ、計算ループの一部であるため、決定的でなければなりません。
Applied Intuition のアプローチ
Applied Development Platform (ADP) のシミュレータは決定的です。決定論を実現するにはいくつかのステップがあります。
- 時間を利用するすべての計算では、シミュレータ自体が作成および管理する合成シミュレーション時間を使用します。Applied Intuition では、シミュレーション結果の決定をシステムクロックに依存しません。
- ADP は確率的アプローチを一切使用していません。ランダムライブラリを使用する場合、シードを疑似乱数ジェネレーターに明示的に設定します。
- 私たちのチームは、並行スレッドとプロセスが入力なしでは実行できないようにシミュレーターを設計し、実行中に線形化ポイントを効果的に作成しました。これにより、計算の順序が毎回同じになることが保証されます。
- ADPの継続的インテグレーション (CI) スイートは、毎日何千ものテストを実行し、毎回まったく同じ結果が得られます。これらのテストでは、考えられるすべての出力の浮動小数点値をゴールデンデータを含むシミュレーションと比較し、コードを変更するたびに同じ結果が得られることを確認します。シミュレータがコードを Applied Intuition のリポジトリにマージできるようにするには、これらのテストに合格する必要があります。これだけでは決定性が保証されるわけではありませんが、他のすべてのアプローチが失敗した場合には、非決定論の問題を見つけるのがずっと簡単になります。
ADP には、GPU アクセラレーションを使用するなど、完全には決定的でない特定のケースがいくつかあります。そのようなケースはごくわずかで、そのすべてが Applied Intuition のドキュメントに記載されており、マクロレベルの決定論には影響しません。
決定論は強力なツールです。これがないと、ADAS と AD の開発チームの自信が失われます。決定論により、チームは迅速かつ自信を持って実行できるようになります。決定論について詳しく知りたい場合、またはADASまたはADスタック内に決定的な動作モードを実装したい場合はエンジニアリングチームにお問い合わせください。