汽車產業的所有主要原始設備製造商(OEM)和軟體供應商都在致力於研發先進駕駛輔助系統(ADAS)。但如果仔細瞭解,你就會對ADAS應用對編譯器和工具集提出的要求產生諸多疑問。傳統的汽車應用和ADAS之間有所區別,為了更好地滿足ADAS需求,需要對目前的編譯器進行一些升級改造。

ADAS應用是一種挑戰

為了更好地支援自動駕駛任務,汽車需要更清楚地瞭解它們的周圍環境。有幾種新的感測器如雷達、雷射雷達、攝影機等,可用來以高解析度檢測路標、其他車輛、障礙物和其他相關的環境資料(圖1)。過去,汽車系統通常只是即時處理來自一些特定執行器(轉向角、踏板位置、各種引擎感測器等)的單獨測量資料。

20170512NT01P1 圖1 基於感測器的不同ADAS應用的監測區域。

然而,與一般的物理測量一樣,ADAS應用採集的環境資料存在雜訊(圖2)和測量誤差。因此,這些資料在可以用於最終用途,即自動幫助司機減輕決策負擔之前,需要用硬體和軟體進行電子後處理。然而,這種後處理並不總是處理像以前那樣的單獨測量資料,很多時候會將來自不同來源的資料合併(感測器融合),從而降低誤差敏感性。

20170512NT01P2 圖2 環境感測器產生的有雜訊訊號及濾波後的結果。

為了使ADAS能夠根據司機行為自動做出決策,ADAS必須能夠即時處理大量資料。另外,這些資料很複雜,以前的做法是只處理整數或定點數類型、速率為1~5kbps的單獨感測器資料。但今天提供的資料經常是浮點類型(浮點/雙精度),而且速率很高。舉例來說,攝影機影像的速率約為340kbps,雷達資料約為1.5Mbps。

很顯然,與傳統的汽車應用相比,ADAS應用要求更強大的處理能力,但現在很難預測哪種高性能的硬體架構更適合這些類型的應用。由於必須以可重複使用和高成本效益的方式實現ADAS應用,因此很明顯對所有架構來說都要求得到編譯器的支援。在這種要求下,必須使用抽象、可移植的設計方法(如C++11/14)、基於模型的設計方法和包括平行程式設計(如OpenCL、Pthreads)在內的其他技術。此外還要求高度優化的、經認證的函式庫來高效、安全地實現標準運算,並盡可能地提高硬體的獨立性。因為ADAS應用會干預駕駛過程,所以這些應用和執行它們的硬體也必須符合相關的安全標準(ASIL-B或更高階的ISO 26262)。

尋找一種合適的硬體架構

對於開發ADAS應用的公司來說,直到現在也沒有哪種硬體架構成為主流,這使它們面臨風險。一般來說,一些主要的硬體加速器——包括NVIDIA GPU的衍生產品(Drive PX)——可以為ADAS應用的資料平行部分提供每秒萬億次浮點運算(Teraflops)等級的足夠運算能力。然而,除了缺少足夠的安全特性外,這些元件就功耗和購買價格而言成本相當高。另一方面,適合直到ASIL-D(包括AURIX或RH850在內)的安全關鍵型應用的典型架構,還沒有利用到硬體方面的機會來實現更高的資料速率,因為這些架構很難通過ASIL-D的認證。

因此,ADAS系統的OEM或大型供應商存在選擇架構的風險,可能會由於架構太大、太昂貴或不能滿足安全要求而賣不出去。另一方面,即使選擇了一種完全支持安全關鍵型應用的架構,也存在這種架構太小無法滿足更嚴格的運算要求的風險。在開發過程中,可能會出現預期應用由於效率原因而無法實現的問題。

因此,ADAS專案的要求非常複雜。一方面,開發人員必須創建非常高效的、特定目標的程式碼,滿足所有安全目標,並儘量減少上述風險。另一方面,有必要採用可移植的高級設計方法進行高成本效益的應用開發。這些高級設計要求,使得原本為傳統嵌入式應用設計的嵌入式編譯器必須作出修改。

程式碼結構的效率

一種必要的新的編譯器特性是需要支援ADAS應用的典型程式碼結構,以便為這類應用創建高效的程式碼。ADAS應用中使用的資料結構及其經歷的運算與經典應用中的有根本區別,用於感測器融合和分析感測器資料的程式碼通常是用BASELABS等模型化工具生成的。舉例來說,ADAS程式碼中與速度有關的部分通常涉及浮點和雙精度類型的陣列(向量和矩陣),這些資料會經歷諸如矩陣乘法、倒數、奇異值分解(SVD)等線性代數運算。系統透過這些運算將感測器資料陣列組合起來運算環境的抽象表述,然後用作決策的基礎(例如檢查影像中的物件,或跟蹤和分配物體的空間位置)。

高度優化的函式庫

這種陣列和浮點數的大量使用,意味著需要對編譯器進行全新的優化,才能提供有效的結果。舉例來說,最常用的線性代數函數一般是由針對特定目標架構高度優化的函式庫所提供。因此,函式庫中沒有包含的所有運算必須用編譯器很好地優化,才能避免這些運算成為瓶頸。

ADAS應用中許多性能關鍵型運算是基於一套標準的線性代數運算實現的。如果這些標準運算使用標準介面,則可以極大地減少將這些ADAS應用移植到不同目標架構所造成的開銷。大多數相關的硬體平台都提供支援標準介面的函式庫,以及針對特定目標架構高度優化的函式庫,包括Tasking為嵌入式應用開發的LAPACK、NVIDIA的cuBLAS和英特爾(Intel)的Integrated Performance Primitives。

一般來說,這些函式庫的速度要比開放原始碼產品或公司內部實現快一個數量級。因此基於標準介面的應用可以很快取得很好的效率,即使在新的目標平台上也可以,而且無需程式設計師自己優化和測試特定目標函式庫中的性能關鍵運算。然而請注意,不是所有的函式庫都針對安全關鍵型應用做了充分的認證,也不是所有函式庫都適合嵌入式系統。

平行程式設計

嵌入式編譯器要求的一個額外的新功能是支援當前的語言,如C++11/C++14。ADAS設計的目標是提高程式碼的可重複使用性,用更少行程式碼實現更多的功能,而又不放棄接近硬體提供的效率。C++這類和繼承是經過時間驗證的方法,非常合適在更高、更抽象的層次編寫這樣的程式碼。

C++11以及後來的版本都支援這些方法,但與更早的C99語言標準相比具有顯著的優勢。另外,C++11(和C11)最終還能用來編寫可移植的平行程式。許多ADAS應用的運算開銷在考慮所有回應時間要求後,經常超過在單核心上實現的連續處理能力。因此,平行和多核心處理是常見的ADAS系統要求。

像C99等舊標準不支援平行機制,因此使用這些語言的程式設計師必須具有很好的硬體和編譯器知識,才能正確編寫出平行程式。舉例來說,程式設計師必須將特定的資料範圍和程式碼片段排除在平行訪問之外,從而確保不會丟失資料更新或在訪問期間錯誤讀取。程式設計師還必須在程式碼中插入屏障(互斥體),防止關鍵部分在同一時間被一個以上的核心執行。

然而,屏障插入技術只有在編譯器理解這些屏障時才有用。如果沒有這樣的概念,那麼在編譯器或硬體優化過程中,編譯器會將這段程式碼移出受保護的部分。在C11/C++11發明之前,還沒有統一的方式來將這種屏障通知給編譯器,因此程式設計師必須禁止全部重要的優化功能,從而導致嚴重的效率下降,或者他們會誤用諸如「volatile」等屬性來限制編譯器的優化功能。現在大家都已知道,使用「volatile」屬性對於編寫正確和可移植的平行程式碼來說是不夠的。

然而,互斥體現在已經是C++標準的一部分,因此C++11編譯器理解所有的屏障概念,編譯器在必要時能夠防止應用出現優化,而導致任何不必要的速度損失。與使用優化不同,程式設計師可以使用C++/C++11引入的「atomic」屬性,編譯器用「atomic」屬性產生的程式碼,可以透過定址硬體來揭示期望的行為,並產生最小的性能開銷。這樣,程式設計師就能專注於他們的主要任務,即程式碼功能,而不用試圖透過不合適的方式(如「volatile」屬性)和優化習慣去產生特定程式碼。

遺憾的是,一般不可能檢測出所有對平行訪問保護錯誤的程式段和資料。有時保護錯誤的程式不會產生任何編譯器錯誤,看起來似乎工作正常,但這些程式可能會因為不明顯的時序問題而自發產生錯誤的結果。這些錯誤一般只出現在很長的測試時間之後。另外,它們也很難重現,因為它們取決於相應的執行時間以及系統內與時間有關的干擾。

因此,即使是用C11/C++11編寫正確的平行程式碼,也不是小事一樁了。自己編寫的平行程式碼也可能存在雖然正確但只比更易維護的、功能相當的順序程式碼快一點點(甚至更慢)的風險。幸運的是,像EMB2和LAPACK等函式庫用起來相對風險就很小,因為它們都是這個領域中的專家編寫的。作為額外的優勢,這些函式庫由於其平行機制及優化,可以確保相對較大的速度提高。

硬體加速器支援

編譯器還需要具備一些新的功能來滿足越來越異構的硬體架構要求。這些架構擁有差別很大的核心(ARM、AURIX、RH850、NVIDIA等)和補充的加速器(如AURIX中的FFT、ARM和NVIDIA中的SIMD),也有多種解決方案。一種方案是原生支持,最直接的方法是支援硬體加速器。這些構造可以用來處理來自C/C++的特殊硬體指令。

更高級的編譯器可以支援加速器供應商提供的特殊高階語言(大多數類似於C),從而說明程式設計師高效滿足硬體要求。例子包括NVIDIA的OpenCL(NVIDIA的編譯器)、GTM的C(Tasking的編譯器)和德州儀器(TI)的EVE擴展C語言。雖然這些高階語言要求編譯和優化,但它們與底層硬體的接近簡化了整個過程。

作為最後一個選項,編譯器可以自動檢測可被加速器高效執行的程式碼區域,以便自動生成合適的程式碼,如同Intel的icc之於SIMD架構。然而,在大多數情況下這種全自動的發現是受限的,因為標準C/C++程式碼不是明確為特定加速器編寫的。不過,只需修改少量的程式碼,編譯器的自動發現就能產生很好的結果,儘管為了在合理的開銷條件下尋找和實現必要的修改,一款合適的調節工具是必不可少。

遺憾的是,許多異構硬體架構強制要求用自己的編譯器定址每個可程式設計單元。為了避免應付過多的不相容工具,防止產生新的安全風險,建議使用能夠定址所有可程式設計單元、確保工具之間互相相容的工具環境。比如Tasking提供的英飛凌(Infineon)AURIX/TriCore工具環境,就可以在一個整合式開發環境(IDE)中程式設計和調試架構中的所有單元。因為符號資訊在不同單元之間是相容的,所以可以更安全地控制和監視單元之間的交互。

ADAS應用的安全要求

為了滿足ADAS應用的特殊安全要求,所有工具(包括建模工具、編譯器和分析工具),以及與這些應用相關的軟體元件(作業系統、函式庫等)必須依據ISO 26262進行開發和認證。

一些較新的安全要求可以利用神經網路來理解(圖3)。神經網路是一些軟體元件,經常用於檢測和處理ADAS應用中的感測器資料。雖然市場上有許多基於神經網路的有趣原型,但仍然不清楚如何確保這些網路在極端情形下有正確的行為。

20170512NT01P3 圖3 一些較新的安全要求可以利用神經網路來理解。

目前還沒有已知的過程可以確保神經網路的行為一直正常,而對道路使用者來說沒有風險。因此,如果沒有合適的監控實體,就不能讓神經網路做出安全關鍵型決策。除了神經網路自己用的硬體外(這些硬體會根據輸入資料提出難以預測的決策建議),必須有一個在硬體上運行的、具有最高安全認證等級(ASIL-D)的監控實體。這個監控實體會使用可預測的演算法工作,檢查由神經網路做出的建議是否能被安全地執行,或者是否應該選擇更安全的方案(圖4)。舉例來說,監控實體會檢查由神經網路建議的通行方案是否能夠在沒有風險的條件下執行,出於這個目的,它會使用自己的、可預測的運算來檢查是否沒有障礙物等。為了創建有效的監控實體,人們仍在努力研究某些領域(比如資料融合)中的可預測演算法。

20170512NT01P4 圖4 資料融合單元。

針對ADAS應用的許多可預測演算法都是基於LAPACK和其他函式庫支援的線性代數運算實現的。可以用優化的解決方案在各種目標平台上高效安全地實現這些演算法。

ADAS應用的其餘部分可以用有助於滿足各種ISO 26262要求的多種工具和技術進行認證。簡單的程式設計錯誤(包括沒有初始化的資料)可以用靜態分析工具(Polyspace、Klocwork等)實現高效檢測。為了檢測與安全相關的訪問違例(具有不同ASIL類別的軟體元件彼此訪問,並在記憶體保護單元(MPU)中創建保護故障),使用編譯器整合的安全檢查器擴展是很有好處的——它能用來定義不同的安全類別(比如ASIL-A到D),將專案中用到的資料和函數分配到不同的安全類別,並管理這些類別之間的存取權限。

然後,這個資訊可以用於兩個目的。首先,編譯器無法執行某些優化(反向程式碼嵌入、程式碼壓縮),因為這些優化在執行時,如果沒有考慮存取權限問題,可能會導致安全訪問違例。其次,可以用安全檢查器工具,將這個相同資訊用於識別可能產生MPU例外、未檢測到的訪問違例,而不會有任何額外的測試開銷,而且有很高的程式碼覆蓋率。

為了依據ISO 26262對工具(建模工具、編譯器、靜態分析、安全檢查器等)進行認證,大多數製造商提供可極大簡化必要過程的ISO套件。在這種情況下,選用在汽車領域中具有悠久歷史的工具和製造商會很有幫助。出於這個目的,ISO 26262-8使用了術語「久經考驗(proven in use)」,它的假設是,一款在很長時間內得到頻繁使用而且幾乎沒有問題的工具,與新工具相比可能不太容易出錯。

除了解決上述安全風險外,編譯器及其相關工具有助於減輕與ADAS應用有關的設計風險。

控制設計風險

如果選擇不合適的硬體、函式庫和開發工具組合,可能會在ADAS領域產生較大的設計風險。目前針對特定的ADAS應用,基本上無法預測特定軟硬體組合的效率。

舉例來說,可能存在所用硬體太大、太耗能或者太小的風險。遺憾的是,目前沒有連續的系列可用:結果證明太小的硬體無法用尺寸稍大一些的相容硬體直接替換。設計人員可以在具有較低安全認證等級的很大配置和具有較高認證等級但小得多的配置之間做出選擇。目前兩種選擇之間的轉換會產生過多的開銷,因為在架構及其最佳使用所要求的程式碼結構之間存在顯著的差異。

目前這個問題可以用編譯器單獨解決。然而,如果有配套的合適軟體環境的話,編譯器可以使得這種風險完全可控。如果能夠將基於特定硬體、高效線性代數函式庫的良好建模解決方案與能夠滿足ADAS應用典型要求的編譯器環境結合起來使用,那麼得到的綜合解決方案將勝過兩者的簡單疊加。

ADAS應用很大程度上可以使用建模解決方案並以獨立於硬體的方式實現。底層的編譯器和函式庫支援將基於模型的通用實現移植到有很大差異的硬體平台上,並且開銷很小,效率很高。由此導致的少量效率不高可以透過性能分析(profiling)來實現快速識別和消除。

對通用程式碼來說,這種組合方案可以在各種目標平台上提供實現最佳效率的確定性捷徑。透過利用一組額外的、根據目標硬體和輸入資料解析度記錄有所有工具的組合效率的基準,這些資料可以用來預測新的ADAS應用在新的目標硬體上的期望效率,並且具有較高的精度。這將極大地降低選擇到不適合預期ADAS應用的目標硬體風險。

目前市場上的編譯器沒有哪種能夠滿足所有要求,完整解決方案所要求的一些工具和函式庫也不是唾手可得。因此,編譯器的路線圖很清晰:必須在不忽略整體解決方案的條件下滿足剩餘要求。舉例來說,Tasking正在規劃新的產品,包括用於AURIX的認證過的LAPACK函式庫,這些產品得到了工具合作夥伴和用戶的大力支持。