word2vec多線程優化時不加鎖的做法合理么?

word2vec的程序中,在訓練模型的時候多線程之間是沒有加鎖的,那麼問題來了:為了簡化描述,僅考慮兩個線程,t1時刻線程1拿到w計算概率和梯度,t2時刻線程2拿到w計算概率和梯度,t3時刻線程1把梯度更新到w里,t4的時刻線程2再更新w時,已經不是算出t2時概率和梯度的那個w了。

當然,同一時刻不同線程處理的葉子節點有可能距離很遠(涉及到的w重疊較少),但是不能排除距離很近甚至是完全相同的可能;再者,越靠近根節點的權重越會存在以上問題。那麼,不考慮word2vec在word analogy和任何NLP場景下取得的結果,從理論上講,這種不加鎖的多線程機制合理么?


想把樓主的問題形式化一下:

樓主認為SGD演算法面對下面這個情況是合理的(w是參數,g是梯度)

w_k = w_{k-1} - g(w_{k-1})

而認為下面這個情況不合理(更新的時候計算梯度所採用的w已經過期了)

w_k = w_{k-1} - g(w_{k-i}) 其中,i大於1

這個問題在優化中,稱作更新步驟中存在delay,在不少paper中已經證明,面對convex的問題,SGD在存在delay的情況下這麼更新依舊有效(不用鎖),參考:Hogwild!: A Lock-Free Approach to Parallelizing Stochastic
Gradient Descent http://www.eecs.berkeley.edu/~brecht/papers/hogwildTR.pdf

當然,word2vec中的優化objective是nonconvex,不過一般實踐中適用於convex的演算法也都是直接用在nonconvex的objective上面,也沒什麼不可以。


發現glove的演算法代碼中也有類似的問題。是不是因為glove演算法有一個shuffle過程,大大降級了被鎖的可能?


答: 十分合理

原因:

1. 高效是word2vec 的一個特色,如果加鎖的話,效率必然降低。

2. 加鎖之後雖然能從理論上提升詞向量的準確性,但是提升的程度非常非常小,假設一個單詞經過N次迭代得到最終的vector,並且假設迭代衝突的次數為n, n一定遠遠小於N, 也就是說由於衝突造成的詞向量精確性的損失非常非常小,幾乎可以忽略不計。

因此,加鎖只會提高很小程度的精確性,卻會大大低效率,所以不加鎖是合理的。


因為詞是稀疏的啊,衝突率不高。而且本來就是隨機梯度下降,即使衝突,因為都是同一時間算的,雖然位置不同,在優化的角度來講,其實還是在向正確方向前進。


我個人覺得還是合理的,類似於神經網路的分散式實現,更新參數只是近似的去做,因為不加鎖肯定會衝突,但這並不會太影響最後的收斂結果,反而還會明顯地加速訓練過程。


反正只要跑到一個大概的終點就可以了,一群人是一擁而上來的快,還是前後怕磕著碰著來的快呢?反正evaluation說話,數學上的嚴格,機器學習家都是糊弄糊弄能說得過去就行。


對矩陣分塊多線程求解,不會有更新同一個參數的問題


推薦閱讀:

ASIO + HTTP 如何打造高性能伺服器?
為什麼`atomic::fetch_add()`可以 relaxed memory order?
make 多線程編譯會出錯么?
CLion 鏈接庫?如 lpthread 怎麼設置?
剛學c++多線程,需要從哪些方面入手,有推薦的教程或書籍嗎?

TAG:機器學習 | 多線程 | word2vec |