我有两个包含不同长度字符串的列表。我需要使用算法将两个列表相互比较,让我们说AlgorithmX将确定是否应该保留ListA中的字符串。这些清单很长(每个清单超过5万个项目),长度可以从1个字符到5000个字符不等。
所以我们至少要查看50 000 * 50 000个比较(而不是直接比较,列表中的每个字符串都通过AlgorthmX
现在我的多线程知识相当低。但我一直在阅读它。但是在.Net中有各种各样的实现。标准线程,任务,等待异步。
使用AlgorithmX使用多线程比较列表的最佳方法是什么?即我应该使用等待异步,任务库吗?
我是否应该按CPU平均分割ListA的项目并针对ListB运行算法?我应该在拆分列表上使用concurrentQueue吗?
[编辑] ConcurrentQueue似乎是我正在寻找的..但欢迎任何添加 http://www.erikbergman.net/2016/03/17/high-speed-applications-parallelism-in-net-part-2/
欢迎任何指示!
答案 0 :(得分:1)
一种可能的实现,它使用ConcurrentQueue
来存储算法决定保留的字符串(注意:没有特别的理由不使用其他一些线程安全的集合)。
此方法使用Parallel.ForEach
来遍历ListA
:
private static void Main()
{
var listA = new[] {"the", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"};
var listB = new List<string>(new[] {"fox", "dog", "cat", "mouse"});
var stringsToKeep = new ConcurrentQueue<string>();
Parallel.ForEach(listA, a =>
{
var shouldKeep = AlgorithmX(a, listB);
if (shouldKeep)
{
stringsToKeep.Enqueue(a);
}
});
Console.WriteLine($"Matching strings: {string.Join(", ", stringsToKeep.ToArray())}");
}
假设:
ListA
和ListB
。只要这些没有被修改,并发访问就没有问题(在多线程环境中对List<>
的只读访问很好 - 只有在修改列表时才会出现并发问题 - 例如Insert /删除/等。)。 AlgorithmX
没有副作用(即方法是“纯粹的”,因此线程安全 - 可以同时调用,没有问题)ListA
中字符串的顺序不需要反映在结果中(即您不关心算法决定保留的字符串的顺序)。答案 1 :(得分:0)
然而.Net中有[多线程]的各种实现。标准线程,任务,等待异步。
使用AlgorithmX使用多线程比较列表的最佳方法是什么?即我应该使用等待异步,任务库吗?
如果您退后一步,可以看到此处async
/ await
不合适。 &#34;并发&#34;一次只做一件事。异步是一种并发形式,不使用专用线程进行操作 - 您可以将其视为更基于事件的。并行性是一种并发形式,它使用多个线程进行操作。异步和并行是两种形式的并发,但它们在实现细节方面是相反的。因此,异步通常用于I / O绑定或其他与CPU无关的任务,如定时器;并行性通常用于CPU工作,就像运行一百万次计算算法一样。
关于并行性,那么有a few tools you have available。一般来说,最好使用具有最高抽象的工具。直接使用手动线程,就像直接使用线程池一样。
在您的情况下,您希望使用Parallel
或Parallel LINQ,它们都构建在任务并行库之上,后者又使用线程池。
有一个great answer using Parallel
already,但我发现如果你需要一个操作的结果,Parallel LINQ通常会产生更简单的代码。在这种情况下:
static List<string> RunAlgorithm(List<string> listA, List<string> listB)
{
return listA.AsParallel()
.Where(a => AlgorithmX(a, listB)).ToList();
}
此代码与其他答案中的Parallel.ForEach
代码具有相同的限制(即,RunAlgorithm
期间未修改列表,AlgorithmX
是线程安全的,以及生成的字符串的顺序没有保留。)
并行LINQ在具有输出的并行算法方面更好一些,并且还有一些专门用于管理这些输出的辅助程序。例如,保留原始订单:
static List<string> RunAlgorithm(List<string> listA, List<string> listB)
{
return listA.AsParallel().AsOrdered()
.Where(a => AlgorithmX(a, listB)).ToList();
}