專案日誌:caffe預測模組和yolo追蹤模組的多gpu多執行緒改進
之前的模式是每個執行緒都有一個單獨的模組例項,需要進行重複的模型載入。
為了實現模型為多個執行緒所複用,需要對模組進行改進。
嫌疑人識別模組和嫌疑車識別模組的結構是一致的,它們都先用yolo進行追蹤,然後用caffe進行分類,所以涉及到這兩個深度學習框架在多執行緒應用方面的改進。
caffe方面,它的部分程式碼採用了單例模式,並用boost::thread_specific_ptr來管理這部分程式碼(我不大清楚為什麼這部分程式碼要用到thread local storage)。這導致沒在一個執行緒中獲取caffe的例項,都會在這個執行緒的local memory中分配記憶體,並進行一些初始化工作。佔用了額外的時間和記憶體。對於這個問題,網上有一種做法是將caffe原始碼中的boost::thread_specific_ptr指標替換成普通的指標,就避免了線上程中分配記憶體和初始化的問題。但是,這樣做在多執行緒場景中會出現漏洞,你必須給獲取例項的get()函式中的初始化程式碼加上double mutex,不然可能會由於多執行緒而初始化不只一個例項,既不可控,也失去了單例模式的意義。還有一種做法是,不再使用單例模式,並將初始化功能從get()函式中分離出來,新增一個專門用於初始化的介面set(),並且保留了boost::thread_specific_ptr。這樣做可以在thread local storage中進行可控的初始化。這些資源由context型別管理,使用者使用context來獲取caffe例項的控制。然後,結合多gpu的應用,作者設計了一個底層由blocking queue實現的context pool,池中的context的數量等於所有gpu上的caffe例項數量之總和。每次使用者要線上程中使用caffe預測,就從池中取出一個context,用完則將其放回池中。於是乎實現了多gpu多執行緒之間模型的複用。
yolo這部分的改進比較棘手,由於要通過幀間目標位移來進行跟蹤,所以需要在物件中維護上一幀目標的資訊。那麼這些資訊為多執行緒所共享,如何在多執行緒間同步這些資訊就需要一番功夫了。目前沒有想到簡單易行的改進方法,只能每個執行緒擁有一個獨立的yolo物件了。