【LDA】修正 GibbsLDA++-0.2 中的兩個內存問題

週末這兩天在家用LDA做個小實驗。在LDA的衆多實現的工具包中,GibbsLDA 是應用最廣泛的,包括c++版本、java版本等。GibbsLDA++ 是它的C++版本的實現,目前最新版本是0.2版。在實際使用過程中,發現這個實現版本有內存使用問題。我花了一些時間定位到了問題,貼出來供大家參考。


問題1:數組內存訪問越界

在model.cpp中,用到了兩個矩陣nw和nd,分別存儲word-topic關係和document-topic關係。這兩個矩陣的大小分別是V * K和 M * K,其中,V是詞表大小,M是文檔個數,K是topic的個數。在sampling的過程中,用隨機數產生器來隨機產生topic對應的索引。源程序如下:

int topic = (int)(((double)random() / RAND_MAX) * K);

原則上,topic的索引的取值範圍是[0,K-1],不過,上面那行程序,函數random()的取值可以是RAND_MAX,也就是說上述語句產生的topic索引的範圍是[0,K],當產生的索引是K的時候,在接下來的運算中,發生數組越界訪問。

所以應該把上面的代碼修正爲:

int topic = (int)(((double)random() / (RAND_MAX+1)) * K);

我實際上是在windows上面用的,windows不支持random()函數,所以改成rand()函數,如下:

int topic = (int)(((double)rand() / (RAND_MAX+1)) * K);

當然,srandom()也要改成srand()。


問題2:內存泄露

內存泄露主要發生在class model的析構函數中,即model::~model()中。產生的原因很簡單,作者對於向量的內存釋放,用的是delete,而正確的應該用delete []。

例如,原始代碼:

if (nw) {
	for (int w = 0; w < V; w++) {
	    if (nw[w]) {
		delete nw[w];
	    }
	}
}

如之前所述,nw是一個矩陣。正確代碼是:

if (nw) {
	for (int w = 0; w < V; w++) {
	    if (nw[w]) {
		delete [] nw[w];   //!!!
	    }
	}
}
	delete [] nw;   //!!!

修改了上面兩個問題之後,GibbsLDA++-0.2在機器上跑的就很順暢了。——其實不修正也能跑出結果來:對於內存訪問越界,次數並不多,所以影響不大;對於內存泄露,進程退出的時候OS會自動清理改進程所用的內存空間,所以也影響不大。這可能也是這個工具包被這麼多人(主要是研究人員)使用,而沒人去修正這個問題的原因吧。


完。


轉載請註明出處:http://blog.csdn.net/xceman1997/article/details/46405597

發佈了167 篇原創文章 · 獲贊 65 · 訪問量 71萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章