C#中HashSet的UnionWith()方法存在性能问题

3

我有许多包含不同索引异常的HashSet。根据输入数据,我将这些hashset组合成一个大的HashSet。为了测试目的,我还将HashSet转换成List类似物。

  • HashSetList的唯一目的是从随机数生成中排除索引。

这就是我在列表情况下所做的:

list2 = new List<int>();
for (int d = 0; d < list1.Count; d++)
{
  if (dicCat4[30].ContainsKey(list1[d]))
  {
    list2.AddRange(dicCat4[30][list1[d]]);
  }
}

rand = 2 * RandString.Next(0 / 2, (dicCat[30].Count) / 2);
while (list2.Contains(rand))
{
  rand = 2 * RandString.Next(0 / 2, (dicCat[30].Count) / 2);
}
// action with random

正如你所看到的,所有异常(索引)都使用 AddRange() 合并为一个列表。我们使用 Contains() 方法检查随机数是否在列表中。

同样的操作也可以使用 HashSet 进行:

excludehash = new HashSet<int>();

for (int d = 0; d < list1.Count; d++)
{
  if (dicCat4[30].ContainsKey(list1[d]))
  {
    excludehash.UnionWith(dicCat3[30][list1[d]]);
  }
}

rand = 2 * RandString.Next(0 / 2, (dicCat[30].Count) / 2);
while (excludehash.Contains(rand))
{
  rand = 2 * RandString.Next(0 / 2, (dicCat[30].Count) / 2);
}
// action with random

在这种情况下,我使用UnionWith()方法来合并索引异常的HashSet,而不是使用AddRange()方法。
奇怪的是,在成千上万次迭代后,List方法的整体性能更好!但根据许多来源,HashSet应该执行得更快。性能分析器显示,最大的性能瓶颈是HashSet的UnionWith()方法。
我只是好奇 - 有没有办法使HashSet方案的性能更快?(我突然想到一个快速的想法:作为替代,我可以在每个单独的哈希集上使用Contains(rand),从而跳过UnionWith()方法)
P.S.哈希集和列表是从以下位置检索的:
static Dictionary<int, Dictionary<int, HashSet<int>>> dicCat3;
static Dictionary<int, Dictionary<int, List<int>>> dicCat4;

编辑:强制迭代解决方案

int inter = list1.Count;
int cco = 0;

while (inter != cco)
{
  cco = 0;

  rand = 2 * RandString.Next(0 / 2, (dicCat[30].Count) / 2);

  for (int d = 0; d < list1.Count; d++)
  {
    if (dicCat4[30].ContainsKey(list1[d]))
    {
      if (!dicCat3[30]][list1[d]].Contains(rand))
      {
        cco++;
      }
      else
      {
        break;
      }
   }
   else
   {
     cco++;
   }
 }
}

1
需要2来生成偶数。0表示最小范围为0(零)。最大值为(dicCat[30].Count)。即rand = [从0到(dicCat[30].Count)]。 - Alex
1
List.AddRange 不检查唯一性,而 HashSet.UnionWith 则会... - digEmAll
是的,列表中有一些重复项。 - Alex
2
我的意思是,由于AddRange仅将新值附加到列表中,它比UnionWith更快,后者还检查添加的值是否会创建重复项(即使速度不是非常 快)。无论如何,对于HashSet调用Contains的循环应该更快(如果调用很多次,则更快)。 - digEmAll
@Alex:我其实不知道你想要达到什么目的,但这个循环对我来说看起来没问题。当然,对于哈希集而言,Contains 比列表更快(除非列表只包含几个元素)。 - digEmAll
显示剩余2条评论
2个回答

1

尝试使用SortedSet而不是HashSet。


0

如果你想在编辑中获得更好的性能,可以尝试交换if/else语句的顺序。C#认为else子句更可能出现,所以会先评估它!这样可以节省几毫秒的时间。但除此之外,我找不到任何其他的节省方法了!

如果你提供一个我可以导入的解决方案,我很乐意去尝试并看看能做些什么,但我不会为了好玩而把它全部打出来! ;)


3
将if和else分支交换是一种微小的优化,这是在物理处理器层面上的优化。 - usr
但是如果她想要挤出尽可能多的速度,那就是一个改善!:P - Faraday
那是因为分支预测器吗? - styfle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接