• 【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()中。产生的原因非常easy。作者对于向量的内存释放,用的是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

  • 相关阅读:
    oracle 数据库关闭的的几种方式总结
    oracle热备份
    oracle 的 startup,startup mount,startup nomount之间的区别
    Oracle数据导入导出imp/exp命令总结
    oracle模糊查询效率可这样提高
    流程控制
    常量
    java序列化
    JVM锁说明
    go变量和数据类型
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7130982.html
Copyright © 2020-2023  润新知