c#中的并行循环,访问同一变量
我有一个c#中的并行循环,访问同一变量,c#,performance,parallel-processing,C#,Performance,Parallel Processing,我有一个项对象,其属性名为generator\u list(字符串的哈希集)。我有8000个对象,对于每个对象,我想看看它的generator\u list是如何与其他generator\u list相交的,然后我想将相交编号存储在list中,该列表逻辑上有8000个元素 这个过程大约需要8分钟,但并行处理只需要几分钟,但我认为并行部分做得不好,因此问题就来了。有谁能告诉我,我是否需要以及如何修改代码以利用并行循环 我的项目对象的代码是: public class Item { publ
项
对象,其属性名为generator\u list
(字符串的哈希集)。我有8000个对象,对于每个对象,我想看看它的generator\u list
是如何与其他generator\u list
相交的,然后我想将相交编号存储在list
中,该列表逻辑上有8000个元素
这个过程大约需要8分钟,但并行处理只需要几分钟,但我认为并行部分做得不好,因此问题就来了。有谁能告诉我,我是否需要以及如何修改代码以利用并行循环
我的项目
对象的代码是:
public class Item
{
public int index { get; set; }
public HashSet<string> generator_list = new HashSet<string>();
}
有什么建议吗?可能是这样的
public Dictionary<int, int> Relatedness2(IList<Item> compare, Item compare_to)
{
int compare_to_length = compare_to.generator_list.Count;
var intersectionData = new Dictionary<int, int>();
foreach (Item block in compare)
{
int block_length = block.generator_list.Count;
int both = 0;
if (compare_to_length < block_length)
{
foreach (string word in compare_to.generator_list)
{
if (block.generator_list.Contains(word))
{
both = both + 1;
}
}
}
else
{
foreach (string word in block.generator_list)
{
if (compare_to.generator_list.Contains(word))
{
both = both + 1;
}
}
}
intersectionData[block.index] = both;
}
return intersectionData;
}
不要忘记可能的字典[i]==null线程安全集合可能就是您要寻找的 在多线程环境中工作时,需要确保 您不能同时操作共享数据,而无需 正在同步访问 NET Framework提供了一些创建的集合类 专门用于并发环境,这是您需要的 当您使用多线程时,请使用。这些藏品是 线程安全,这意味着它们在内部使用同步来 确保多个线程可以同时访问它们 时间 来源:C#考试参考70-483中的编程,目标1.1:使用并发集合实现多线程和异步处理 以下哪些是收藏
BlockingCollection
ConcurrentBag
ConcurrentDictionary
ConcurentQueue
ConcurentStack
var items = new List<HashSet<string>>
{
new HashSet<string> {"1", "2"},
new HashSet<string> {"2", "3"},
new HashSet<string> {"3", "4"},
new HashSet<string>{"1", "4"}
};
var intersects = items.AsParallel().Select( //Outer loop to run on all items
item => items.AsParallel().Select( //Inner loop to calculate intersects
item2 => item.Intersect(item2).Count())
//This ToList will create a single List<int>
//with the intersects for that item
.ToList()
//This ToList will create the final List<List<int>>
//that contains all intersects.
).ToList();
var items=新列表
{
新哈希集{“1”,“2”},
新哈希集{“2”,“3”},
新哈希集{“3”,“4”},
新哈希集{“1”,“4”}
};
var intersects=items.aspallel()。选择(//要在所有项上运行的外部循环
item=>items.aspallel()。选择(//内部循环以计算相交
item2=>item.Intersect(item2.Count())
//此列表将创建一个列表
//与该项的相交
托利斯先生()
//此列表将创建最终列表
//包含所有交叉点的。
).ToList();
运行它时会发生什么?除非您想自己实现一个并发收集对象,否则您应该考虑使用一个并发收集对象,比如这个对象。另请参见:。您好,当我实际运行它时,它工作了,我曾经在该项目的属性中存储每个项目的列表结果抱歉,我在并行代码中编辑了一行,因为我必须在粘贴到此处之前修改代码,以使其更易于阅读,并行代码行看起来一定很奇怪,因为我使用了一个变量,我在其他地方没有提到,但这只是复制和粘贴我的代码并试图清理它的结果,我现在修复了它谢谢,我会尝试这个。我唯一的问题是,对于每个项目,因为它与其他项目相交,所以我希望将每个项目的所有结果存储在一个列表中。所以它看起来像7,{23,34,0,0,45100…}这意味着项目7(基于索引,它是唯一的),有一个23与项目0的交集,34与项目1的交集,。。。等等你知道我如何修改你的代码来实现这个吗?哦,等等,我刚刚运行了代码,而且速度非常快。我将尝试确认结果,我认为你的字典确实给出了我想要的值,我只是误解了你的代码。对不起,我今年夏天才开始编程!您认为您可以更新您的答案并添加此代码吗?在评论中我似乎没能很好地理解它:(谢谢,非常感谢!Parallel.ForEach(readOnlyItems.Take(1000).ToList(),item=>{dictionary[item.index]=Relatedness2(readOnlyItems,item);});这将使您获得列表前1000项的所有交叉点谢谢,我也一定会尝试!我只有机会尝试另一个答案的代码,而且我整天都在上课,呃,但一旦我有空,我也会尝试实现它。嗨,我很好奇,newItem
的目的是什么?我理解这些项目,我想继续试试这个,但我的代码中没有与newItem
等效的代码?@user340897可能我误解了你的代码。我以为你想将一个项目与你的项目列表进行比较,并获得列表中每个现有项目与该新项目的相交数。不过,看起来你已经找到了答案。是的,我这么认为rt是的,当我用数据的一个子集运行它时,速度非常快,但是对于所有的数据,速度和我以前的一样快……是的,现在我更好地看到了你的代码,我有点理解了,但是你能告诉我如何更改它,以便它自动循环列表中的所有项目吗?看起来你的代码只是在这样做有一个问题?@user340897更新了答案,让我知道性能。谢谢,但由于我今年夏天才开始编程,这种信息在我脑海中飞过。哈哈。但我想我明白了重点,特别是因为其中一个答案使用了并发字典,它开始揭示整个主题。
public Dictionary<int, int> Relatedness2(IList<Item> compare, Item compare_to)
{
int compare_to_length = compare_to.generator_list.Count;
var intersectionData = new Dictionary<int, int>();
foreach (Item block in compare)
{
int block_length = block.generator_list.Count;
int both = 0;
if (compare_to_length < block_length)
{
foreach (string word in compare_to.generator_list)
{
if (block.generator_list.Contains(word))
{
both = both + 1;
}
}
}
else
{
foreach (string word in block.generator_list)
{
if (compare_to.generator_list.Contains(word))
{
both = both + 1;
}
}
}
intersectionData[block.index] = both;
}
return intersectionData;
}
List<Item> items = new List<Item>(8000);
//add to list
var dictionary = new ConcurrentDictionary<int, Dictionary<int, int>>();//thread-safe dictionary
var readOnlyItems = items.AsReadOnly();// if you sure you wouldn't modify collection, feel free use items directly
Parallel.ForEach(readOnlyItems, item =>
{
dictionary[item.index] = Relatedness2(readOnlyItems, item);
});
var intesectiondata = dictionary[1]//dictionary of intersection for item with index 1
var countOfintersectionItemIndex1AndItemIndex3 = dictionary[1][3]
var countOfintersectionItemIndex3AndItemIndex7 = dictionary[3][7]
var items = new List<HashSet<string>>
{
new HashSet<string> {"1", "2"},
new HashSet<string> {"2", "3"},
new HashSet<string> {"3", "4"},
new HashSet<string>{"1", "4"}
};
var intersects = items.AsParallel().Select( //Outer loop to run on all items
item => items.AsParallel().Select( //Inner loop to calculate intersects
item2 => item.Intersect(item2).Count())
//This ToList will create a single List<int>
//with the intersects for that item
.ToList()
//This ToList will create the final List<List<int>>
//that contains all intersects.
).ToList();