性能问题

时间:2011-01-19 11:01:59

标签: c#

好的,所以我需要知道是否有人能看到减少这些循环迭代次数的方法,因为我不能。第一个while循环用于浏览文件,一次读取一行。然后,第一个foreach循环将compareSet中的每一个与第一个while循环中读取的内容进行比较。然后下一个while循环与位计数有关。

根据要求,解释我的算法:

有一个文件太大而无法放入内存中。它包含一个单词,后跟一个非常大的文档中的页面。 EG:

sky 1 7 9 32 .......(不是这种格式,但你明白了。)

所以parseLine读入该行并将其转换为一个类似于位数组的整数列表,其中1表示该单词在页面上,0表示不是。

CompareSet是一堆其他的词。我无法将我的整个单词列表放入内存中,因此我只能拟合其中的一部分。这是一堆词,就像“天空”的例子。然后,我将compareSet中的每个单词与Sky进行比较,看看它们是否在同一页面上。

因此,如果天空和其他一些词在位数组中的某个索引处都有1个设置(模拟为性能的int数组),则它们位于同一页面上。因此,算法计算特定页面上任何两个单词的出现次数。所以最后我会有一个列表:

(对于列表中的所有单词)与(对于列表中的所有单词)x次在同一页面上。

例如,天空和陆地在同一页上x次。

 while ((line = parseLine(s)) != null) {
     getPageList(line.Item2, compareWord);
     foreach (Tuple<int, uint[], List<Tuple<int, int>>> word in compareSet) {
         unchecked {
             for (int i = 0; i < 327395; i++) {
                 if (word.Item2[i] == 0 || compareWord[i] == 0)
                     continue;
                 uint combinedNumber = word.Item2[i] & compareWord[i];
                 while (combinedNumber != 0) {
                     actual++;
                     combinedNumber = combinedNumber & (combinedNumber - 1);
                 }
             }
         }

2 个答案:

答案 0 :(得分:2)

正如我的老教授巴德曾经说过的那样:“当你看到这样的嵌套循环时,你的蜘蛛般的感官应该疯狂!”

你有一段时间与另一个嵌套for。这种循环嵌套是操作顺序的指数增加。你的一个for循环有327395次迭代。假设它们具有相同或相似的迭代次数,则意味着您具有

的操作顺序
327,395 * 327,395 * 327,395 = 35,092,646,987,154,875 (insane)

毫无疑问,事情会变慢。您需要重新定义算法以删除这些嵌套循环或在某处组合工作。即使数字小于我的假设,循环的嵌套也会产生很多可能不必要的操作。

答案 1 :(得分:0)

正如Joal已经提到的,没有人能够优化这种循环算法。但你可以做的是试图更好地解释你想要完成什么以及你的硬性要求是什么。也许您可以通过使用HashSet<T>.IntersectWith()BloomFilter之类的内容来采取不同的方法。

因此,如果您真的需要这里的帮助,您不仅应该发布不起作用的代码,还要发布您想要完成的整体任务。也许有人有一个完全不同的想法来解决你的问题,使你的整个算法过时。