1. 程式人生 > >影象檢索伺服器編寫問題記錄——服務端的任務佇列執行緒分配的反思

影象檢索伺服器編寫問題記錄——服務端的任務佇列執行緒分配的反思

這個影象檢索伺服器在服務端的工作:1.接收客戶端發來的圖片+2.計算圖片特徵向量,匹配特徵庫影象+3.發回topK的相似圖片。

上版的做法:一個eopll主執行緒迴圈檢測是否有連線進來==》檢測到連線,裝填讀任務佇列==》讀任務排程執行緒迴圈檢測是否有讀任務==》檢測到讀任務,分派工作執行緒去處理==》工作執行緒讀完客戶端發來的圖片,裝填計算圖片片特徵向量,匹配特徵庫影象佇列===》計算佇列排程執行緒檢測到計算任務,分派工作執行緒去處理==》。。。。

將任務拆分成了3級任務佇列:讀圖片(佔用IO)+計算特徵向量和計算相似度(佔用cpu)+寫相似度topK的圖片給客戶端(佔用IO)。原本的意願是希望某個執行緒在讀圖片的過程中(佔用IO),其他執行緒可以去計算特徵向量和計算相似度(佔用cpu),以此做成流水線,因為執行緒池的執行緒個數總是有限的,如果做成單任務佇列形式的話,會出現明明IO空閒著,但因為執行緒池沒有執行緒導致不能利用這段空閒時間去讀圖片。【計算任務的耗時遠大於讀,寫圖片

】如圖,當初的想法:


想法是好的,但是我的三個任務佇列同用一個執行緒池,那就有問題了。當讀任務佇列,計算任務佇列,寫任務佇列都有任務時,這個喚醒執行緒是去讀?還是寫?還是計算?只有鬼知道了。極端情況,假如我有4核cpu,可以同時處理四個計算任務;現在有6個執行緒,喚醒後都被拿去處理計算任務,那麼cpu會頻繁的切換這6個執行緒,因為cpu核只有4個。再假設我將執行緒數設定成cpu核數4,這固然可以解決cpu頻繁切換的問題,但是還是上面的問題,極端情況,4個執行緒都被拿去處理計算任務了,那麼一堆的寫回任務堆積在那邊,沒有處理,伺服器處理整個任務的時長依然很長。沒有完全達到流水的目的。

改進的想法是:讀圖片、計算任務、寫回圖片均有自己的執行緒池。

讀、寫的執行緒池中執行緒個數均為1:計算任務耗時遠大於讀、寫,所以讀寫即使是阻塞的讀,阻塞的寫都沒關係,因為計算任務等的起。

計算特徵向量的執行緒池中的執行緒個數為4(cpu核數):>4後頻繁切換

另:讀、寫的執行緒無任務時用條件變數阻塞(或用sleep,但是sleep的壞處是首次喚醒必須等待一段時間),如此防止空轉。