【发布时间】:2012-08-08 20:36:02
【问题描述】:
我有一个书签列表。每个书签都有一个关键字列表(存储为 HashSet)。我还有一组所有可能的关键字(“宇宙”)。
我想找到出现在书签中最多的关键字。
我有 1356 个书签,总共有 698,539 个关键字,有 187,358 个唯一关键字。
如果我遍历宇宙中的每个关键字并计算它出现在书签中的数量,我将进行 254,057,448 次检查。这在我的机器上需要 35 秒。
算法很简单:
var biggest = universe.MaxBy(kw => bookmarks.Count(bm => bm.Keywords.Contains(kw)));
我不确定是否可以加快速度,但有什么我可以做的吗?也许以某种方式并行化它?
dtb 的解决方案需要不到 200 毫秒的时间来构建宇宙并找到最大的元素。就这么简单。
var freq = new FreqDict();
foreach(var bm in bookmarks) {
freq.Add(bm.Keywords);
}
var biggest2 = freq.MaxBy(kvp => kvp.Value);
FreqDict 只是我在Dictionary<string,int> 之上构建的一个小类。
【问题讨论】:
-
在等待 35 秒过去时,它会给 CPU 带来多大压力?
-
@IneedHelp:查看任务管理器 (Win7) 中的性能选项卡,CPU 使用率从 1% 跃升至 25% 左右,然后稳定在 12% 左右。我有 4 个内核,超线程到 8 个。
-
@Mark:你有没有考虑在创建全域的时候统计每个关键词出现的次数?
-
@dtb:不……我没想到。创建宇宙只需要100ms;它只是在做一堆
UnionWiths。如果我改用Dictionary<string,int>并进行一些计数,我想它不会慢很多,它会给我更多信息。好奇的。不管怎样,我想递归地应用这个,用一个“缩小的宇宙”——也就是说,我正在为集合覆盖问题实施一个贪婪的解决方案。我想我仍然可以应用此解决方案,但我不会第二次添加任何新条目。明天早上试试。谢谢! -
@Mark 除了计数之外,对于并行化,您始终可以尝试对来自
PLINQ的universe.AsParallel()...进行基准测试。请注意,它没有必须更快...
标签: c# algorithm optimization hashset