當前參與交付的語音識別產品服務,演算法模組基於經典的Kaldi,演算法中的一部分執行在GPU之上。
演算法團隊採用的是聲學模型+語言模型的1-pass方案。這個方案的特點在於,語言模型資料檔案(HCLG檔案)的大小,和訓練語料的豐富程度正相關,即語言文字的語料越多,經過訓練、轉換後得到的語言模型檔案越大。
經過資料團隊一段時間的努力,當前專案使用的語言模型,已經達到了 XX GB的規模。
這對我負責交付的演算法服務元件帶來了全方位的挑戰:
- 版本構建,耗時接近30分鐘。
- 安全掃描,耗時接近30分鐘,運氣不好的話,可能會上升至1小時+。
- 版本上傳軟體倉庫,耗時至少10分鐘。
- 版本部署,耗時約30分鐘。
- 服務啟動,耗時5分鐘,其中主要時間都用來解析、載入語言模型檔案。
平時在開發的部署環境上遠端除錯業務時,需要反覆給服務打補丁、重啟,由於啟動時間耗時在5分鐘,因此除錯效率很低。受限於硬體規格,除錯效率低的問題一直沒有很好的解決方法,於是開發小夥伴們只好忍著。
但終於有一天的晨會上,開發小夥伴向我抱怨,現在除錯演算法服務時效率非常低,啟動程式時,至少需要兩次,等待10分鐘,才能將程式執行起來。小夥伴們反覆驗證,發現打補丁之後,第一次啟動演算法服務時一定會啟動失敗。小夥伴反饋的這個資訊,一開始我並沒有放在心上,但事後證明這是一個大的疏忽。
後來,我交付的一個需求,程式碼在本地使用UT用例驗證完畢,進入在環境上做功能驗證的環節。這時由於需要反覆的對環境打補丁、重啟服務,修復遠端除錯過程中發現的問題,同樣的,我也遇到了小夥伴反饋的現象。不過這個現象被我誤判斷為網路問題,因為那段時間網路特別差,經常斷網,導致控制檯程式隨機斷開,這也會導致服務啟動不成功。
網路的問題很好修復,並且持續的時間比較短。而我自己UT做的相對比較充分,因而花在遠端除錯的時間比較短,因此業務需多次啟動的問題,對我的困擾不大。於是,這個多次啟動的問題被我輕易放過了。
版本轉測試之後,測試同事反饋兩個現象:
- 在配置中心修改配置後,無法自動生效。
- 測試同事部署新版本之後,需要至少需要啟動兩次,才能把服務正常執行起來。
這兩個現象都很奇怪。
對於第一個現象,我們基於基礎平臺來交付業務,很多產品的服務都使用這套框架,而我們團隊內部其它的服務也使用了這套框架,都沒有遇到過在配置中心修改配置後不生效的現象。
對於第二個現象,正常情況下,使用部署工具完成演算法服務的部署之後,演算法服務本身是應該處於執行狀態的。但測試同學發現使用最近的版本安裝完成之後,演算法服務經常處於啟動失敗的狀態。而手工啟動時,至少需要兩次啟動,才能啟動成功。
測試同事是在做效能壓力測試的準備工作時觀察到的前述現象,雖然暫時不會阻塞效能測試,但本著懷疑一切、不能放過問題的精神,測試同事提交了問題單,要求儘快解決。於是,現在不能當成偶然事件放過了,需要認真對待,否則必然影響版本釋出。
對於測試同事反饋的第一個問題,為便於後續的說明,這裡先介紹一下配置管理的實現方案。
配置管理服務,包括配置中心和cnfg_agent。
- 配置中心集中部署,提供Web介面供使用者管理、維護應用服務的配置項和值。
- cnfg_agent和業務服務元件同機部署,使用相同的執行賬號,定時從配置中心服務讀取配置項和值,並寫入本地檔案,由業務服務元件讀取。
經過觀察測試同事的環境,有如下發現:
- 環境上的cnfg_agent程式沒有處於執行狀態。手工啟動cnfg_agent後,在配置中心修改的配置值,可以被cnfg_agent正常同步至本地。由此可以確認cnfg_agent自身的業務功能是正常的。
- 兩次啟動演算法服務後,發現cnfg_agent程式消失了,因此需要確認cnfg_agent消失的原因。
聯絡配置管理服務的技術支援同學,瞭解到cnfg_agent的工作原理。
- cnfg_agent安裝過程中,安裝指令碼會自動定義一個cron任務。
- 在cron任務的指令碼程式碼中,會主動檢查cnfg_agent程式是否存在,如不存在,則拉起cnfg_agent程式。
因此,即便是cnfg_agent由於自身的原因退出執行,理論上講,應該很快被定時執行的cron任務檢測到異常,並自動啟動,不應該出現cnfg_agent長時間處於離線狀態的現象。
進一步檢查測試同事提供的環境,發現一個新的現象。如前所述,cnfg_agent和業務元件同機部署,使用了相同的作業系統的賬號。檢查測試環境的主機,發現業務賬號恰好沒有建立cron任務的許可權,這意味著安裝cron定時任務的操作一定失敗。因此當cnfg_agent程式退出後,沒有定時任務來檢測、並重新拉起cnfg_agent程式。這可以解釋為什麼cnfg_agent消失後不能自動恢復執行。
於是,在測試環境上,手工給業務賬號增加建立、執行cron任務的許可權,並增加cnfg_agent的cron任務。之後嘗試多次重啟演算法服務,發現cnfg_agent雖然會退出執行,但很快就會被cron任務拉起。
因此cnfg_agent程式退出後無法恢復執行的問題,可以使用本方法臨時規避。
繼續分析。
檢查cnfg_agent的日誌檔案,在啟動演算法服務的時間點,找到了cnfg_agent退出執行的日誌記錄。
對於我們提供的資訊,配置管理服務的技術支援同學給出的答案是,cnfg_agent退出執行,通常只在作業系統重啟時才有可能會遇到。
按照這個答覆,檢查/var/log/messages
,居然真的找到了作業系統重啟的日誌記錄,同時觀察到了核心crash的記錄。檢查時間點,發現啟動演算法服務、cnfg_agent退出執行,這三件事的時間點相同。
這時,基本可以把演算法服務第一次啟動失敗、cnfg_agent退出執行、作業系統重啟,這三件事情關聯在一起分析。
聯絡作業系統專家,在其協助下,順利的找到了作業系統重啟的原因。原來是出現了核心crash現象,並且在出現問題的一臺主機上提取到了核心crash的相關記錄。
我們當前部署演算法服務的主機,基於CentOS定製,安裝了kdump工具。作業系統專家依據kdump生成的crash資訊,找到兩類原因:
- 主機的記憶體不足,觸發核心crash。
- GPU驅動的程式碼中存在一處bug,申請記憶體後,沒有對指標判空,當申請記憶體失敗時,C庫返回的是空指標,這時GPU驅動的程式碼直接操作這個指標,觸發了空指標異常,進而導致核心crash。
這兩個原因都和記憶體相關。
和作業系統專家、基礎設施專家交流後,依據他們的建議,選擇一臺存在問題的主機,提交擴充規格的申請,將記憶體放大一倍。再復現操作,發現演算法服務只需一次即可正常啟動。
經反覆重試後,確認:
- 核心不再crash。
- cnfg_agent不會出現重啟現象。
- 演算法服務只需一次即可啟動。由於擴充規格後,CPU數量蠻多,現在啟動演算法服務的時間也縮短了。
因而有理由推斷:
- cnfg_agent的意外重啟現象,和cnfg_agent自身的質量無關,和作業系統重啟強相關。
- 作業系統的重啟現象,主要由核心crash導致。
- 而核心crash現象,目前看和演算法服務所在主機的硬體規格過低相關。
- 擴充規格後,一切問題現象全部消失。
將前述定位的資訊同步給測試同事,經過討論之後,測試同事基本認可分析結論。
大家達成一致結論:
- 對於硬體規格不足的問題,同意調整測試環境中主機的規格,繼續執行其餘的驗證。
- 對於GPU驅動中存在的問題,需要演算法同事介入,驗證高版本的GPU驅動是否解決了相關的問題。
- 假如高版本的GPU驅動解決了問題,涉及到的版本升級、版本部署包、安裝指導等的更新,暫時先放在任務清單。
後記:
升級硬體規格之後,作業系統核心crash的現象不再出現。但前述描述的原因和現象之間的關係,個人感覺還是有點牽強。比如在重啟應用時,這時系統其實處於空載狀態,記憶體佔用率、顯示卡的記憶體佔用率,實際上比較低,但核心仍然會出現crash事件,比較怪異。由於不具備分析核心、驅動類故障的技能和經驗,並且無法獲得作業系統專家進一步的協助,因此本事件暫時放一放。
如下是kdump相關的帖子: