百度自動駕駛C++開發面試經歷:ROS+感知演算法+即時系統全考察
2年自動駕駛C++開發經驗,詳細復盤百度自動駕駛C++面試三輪技術面全過程,涵蓋C++11/14/17新特性、記憶體管理、ROS通信架構、感知演算法部署最佳化等核心考點
背景介紹
我做了2年自動駕駛C++開發,之前在一家自動駕駛創業公司做感知模組的開發,主要用C++和ROS。百度Apollo一直是國內自動駕駛的標杆,尤其是他們的開源生態,我之前專案裡就用了不少Apollo的程式碼。我投的是百度自動駕駛C++開發崗,整個面試流程大概三週,三輪技術面+一輪HR面,難度確實很高,每一輪都有讓我「卡住」的題目。
準備面試的時候,我重點複習了C++11/14/17的新特性、記憶體管理、ROS的通信機制、感知演算法的原理,還有即時系統的設計。百度的面試官技術功底很深,問的問題不是那種浮於表面的概念題,而是真正考驗你對底層原理的理解。
面試流程復盤
一面:C++11/14/17 + 記憶體管理
一面的面試官是個看起來很有經驗的工程師,應該是做基礎架構的。開場先聊了聊我的專案經驗,然後直接進入C++技術環節。
第一個問題就很硬核:C++11的move語義是什麼?右值引用和左值引用的區別?我從右值的定義講起,說了將亡值(xvalue)的概念,然後詳細講了move constructor和move assignment的實現。面試官追問了std::move到底做了什麼?它真的移動了資料嗎?我解釋了std::move只是一個型別轉換(static_cast
智慧指標部分:shared_ptr的引用計數是怎麼實現的?執行緒安全嗎?我講了控制塊(control block)的實現,引用計數是原子操作所以是執行緒安全的,但指向的物件本身不是執行緒安全的。面試官追問了shared_ptr的循環引用問題怎麼解決?weak_ptr的原理是什麼?我詳細說了weak_ptr不增加引用計數、lock()方法回傳shared_ptr、expired()方法檢查是否過期。
C++14/17新特性:std::optional、std::variant、std::any的適用場景?我對比了三者的設計意圖:optional表示可能沒有值、variant表示型別安全的聯合體、any表示任意型別的容器。面試官追問了variant和union的區別?variant的存取方式有哪些?我講了variant是型別安全的、支援visit模式匹配,而union不是型別安全的。
記憶體管理部分:malloc和new的區別?記憶體池的設計思路?我講了new會呼叫建構函式而malloc不會、new失敗拋例外而malloc回傳NULL。然後說了記憶體池的預分配+空閒鏈表的方案,以及如何減少記憶體碎片。面試官最後問了一個綜合題:如果程式執行一段時間後記憶體持續增長但不釋放,你怎麼排查?我提到了Valgrind、AddressSanitizer、以及自定義的記憶體分配器來追蹤分配和釋放的配對。
一面大概65分鐘,C++部分佔了大頭。面試官最後說「C++基礎扎實,但記憶體管理這塊可以再深入」,給了我二面機會。
二面:ROS + 感知演算法
二面的面試官明顯是做感知演算法的,問的問題非常專業。開場就問:ROS的通信機制有哪些?各自的優缺點?我講了Topic(發布/訂閱,非同步)、Service(請求/回應,同步)、Action(長時間任務,可取消)三種機制。面試官追問了ROS1和ROS2在通信架構上的本質區別,我詳細說了DDS中介軟體、QoS策略、以及去中心化的發現機制。
感知演算法部分是重頭戲:點雲處理中體素濾波(Voxel Grid Filter)的原理是什麼?我講了將3D空間劃分為體素網格、每個體素內用質心代替所有點的過程。面試官追問了體素大小怎麼選擇?太大會怎樣?太小會怎樣?我回答了太大會丟失細節、太小則降取樣效果不明顯,需要根據場景和感測器精度來權衡。
目標偵測:PointPillars的架構是怎樣的?和PointNet++相比有什麼優勢?我詳細講了PointPillars將點雲轉換為偽影像(pseudo-image)的流程:Pillar Feature Network → 2D CNN Backbone → Detection Head。然後對比了PointPillars在推理速度上的優勢(因為可以用2D卷積),以及在小目標偵測上的劣勢。面試官又問了一個很實際的問題:在實際部署中,感知模型的延遲要求是多少?你怎麼最佳化推理速度?我提到了TensorRT加速、INT8量化、模型剪枝等方法。
多感測器融合:光達和相機的資料怎麼融合?前融合和後融合的區別?我講了前融合是在特徵層面融合(如PointPainting),後融合是在決策層面融合(如分別偵測再合併結果)。面試官追問了時間同步問題怎麼解決?我提到了硬體同步(PPS訊號)、軟體時間戳對齊、以及插值補償的方法。
二面最後問了一個開放題:如果感知模組在某個場景下誤檢率很高,你怎麼分析和解決?我提出了資料驅動的分析思路:先統計誤檢的分佈特徵,然後分析是否是資料分佈偏移、標註品質問題、還是模型本身的限制,最後針對性地增加資料、調整模型或加後處理規則。
三面:即時系統 + 專案深挖
三面是技術總監面的,風格更像技術討論。先讓我講了一個最有挑戰的專案,我選了之前做的多目標追蹤(MOT)模組的最佳化。他追問了追蹤演算法的選型依據、ID切換問題的解決方案、以及即時性保證,每個點都問得很細。
即時系統部分:自動駕駛系統對即時性的要求是什麼?硬即時和軟即時的區別?我講了硬即時是必須在截止時間內完成否則會導致系統失敗,軟即時是盡量滿足但不滿足也不會崩潰。面試官追問了你們系統的端到端延遲是多少?怎麼保證的?我回答了感知模組的延遲要求在100ms以內,透過執行緒優先級設定、CPU親和性繫結、以及鎖-free的資料結構來保證。
系統設計題:設計一個自動駕駛的感知系統,需要支援多感測器輸入、即時處理、故障偵測。這個題很大,我從架構分層開始:驅動層(感測器資料採集)、預處理層(時間同步、座標變換)、演算法層(偵測+追蹤+融合)、輸出層(結果發布和故障偵測)。重點講了雙冗餘的故障偵測機制和優雅降級策略。面試官追問了如果某個感測器突然故障,系統怎麼處理,我講了感測器健康度監控、自動切換到降級模式、以及通知規劃模組調整策略的方案。
三面最後聊了聊自動駕駛行業的發展,面試官很坦誠地分享了他對L4量產時間表的看法。整體感覺百度Apollo的技術氛圍很好,面試官都是真正做技術的人。
真題彙總
一面:
1. C++11 move語義、右值引用和左值引用的區別
2. std::move的本質,移動後源物件的狀態
3. shared_ptr引用計數實現和執行緒安全性
4. weak_ptr原理和循環引用解決方案
5. std::optional、variant、any的適用場景
6. variant和union的區別
7. malloc和new的區別,記憶體池設計思路
8. 記憶體洩漏排查方法
二面:
1. ROS通信機制(Topic/Service/Action)
2. ROS1和ROS2通信架構的本質區別
3. 體素濾波原理和引數選擇
4. PointPillars架構及與PointNet++對比
5. 感知模型部署最佳化(TensorRT、量化、剪枝)
6. 光達和相機資料融合方案
7. 多感測器時間同步問題
8. 感知誤檢率高的分析和解決思路
三面:
1. 多目標追蹤模組最佳化專案深挖
2. 追蹤演算法選型、ID切換解決、即時性保證
3. 硬即時和軟即時的區別
4. 系統端到端延遲保證方案
5. 系統設計:自動駕駛感知系統
6. 感測器故障處理和降級策略
心得建議
1. C++要理解到語言標準層面:百度的C++面試不會只問你語法,一定會問到語言標準的設計意圖和底層實現。move語義、智慧指標、模板元程式設計,這些都要能說出「為什麼」。
2. ROS要理解到架構層面:不只是會用roslaunch,要理解ROS的通信架構、DDS中介軟體的原理、以及ROS2相比ROS1的改進。如果你只用過ROS1,建議至少了解一下ROS2的設計理念。
3. 感知演算法要有實戰經驗:百度不會只問你論文裡的演算法,會問你實際部署中的問題。推理最佳化、感測器融合、故障處理,這些都需要有實際經驗或者深入的思考。
4. 即時系統是加分項:自動駕駛對即時性的要求很高,如果你能說清楚怎麼保證即時性(執行緒調度、CPU親和性、鎖-free設計),會大大加分。
5. 系統設計要從自動駕駛場景出發:百度的系統設計題不是通用的,而是和自動駕駛緊密結合的。你需要考慮感測器故障、即時性約束、安全等級這些自動駕駛特有的問題。
FAQ
Q:百度自動駕駛C++面試對C++的考察深度如何?
A:很深,不會只問語法層面,一定會追問到語言標準的設計意圖和底層實現。比如move語義的本質、智慧指標的執行緒安全性、variant的型別安全保證等。
Q:沒有ROS經驗可以面自動駕駛崗嗎?
A:比較難。百度的自動駕駛崗幾乎都要求ROS經驗,至少要理解ROS的通信機制和開發流程。如果沒有,建議先做幾個ROS專案練手。
Q:感知演算法需要掌握到什麼程度?
A:至少要能說清楚主流演算法的原理和優劣,以及實際部署中的最佳化方法。不需要從頭實現,但要有足夠的理解來討論技術選型。
Q:面試中會問演算法題嗎?
A:我面的三輪沒有單獨的LeetCode題,但感知演算法部分會涉及演算法設計。不過聽說有的面試官會加一輪演算法,建議還是準備一下。
Q:百度Apollo的工作氛圍如何?
A:從面試體驗來看,技術氛圍很好,面試官都是真正做技術的人。三面的技術總監對行業有很深的理解,交流很愉快。