Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有什么能比并发集合更好地解决这个多线程场景_C#_Multithreading_Dictionary_Concurrency_Concurrentdictionary - Fatal编程技术网

C# 有什么能比并发集合更好地解决这个多线程场景

C# 有什么能比并发集合更好地解决这个多线程场景,c#,multithreading,dictionary,concurrency,concurrentdictionary,C#,Multithreading,Dictionary,Concurrency,Concurrentdictionary,我有一个持久的B+树,多个线程正在读取树的不同块,并对读取的数据执行一些操作。有趣的是:每个线程产生一组结果,作为最终用户,我希望在一个地方看到所有结果。我所做的:一个ConcurentDictionary,所有线程都在向它写入 这样一切都很顺利。但应用程序是时间关键型的,多出一秒钟意味着完全不满意。由于线程安全开销,ConcurentDictionary与Dictionary相比本质上是缓慢的 我可以使用字典,然后每个线程将结果写入不同的字典。但是我会遇到合并不同词典的问题 我的问题是: 对

我有一个持久的B+树,多个线程正在读取树的不同块,并对读取的数据执行一些操作。有趣的是:每个线程产生一组结果,作为最终用户,我希望在一个地方看到所有结果。我所做的:一个ConcurentDictionary,所有线程都在向它写入

这样一切都很顺利。但应用程序是时间关键型的,多出一秒钟意味着完全不满意。由于线程安全开销,ConcurentDictionary与Dictionary相比本质上是缓慢的

我可以使用字典,然后每个线程将结果写入不同的字典。但是我会遇到合并不同词典的问题

我的问题是:
  • 对于我的场景,并发收集是一个好的决策吗
  • 如果不是(1),那么如何以最佳方式合并不同的词典。考虑到,(a)逐个复制项和(b)LINQ是已知的解决方案,并不像预期的那样最优:)
  • 如果不是(2);-)你有什么建议
  • 快速信息:


    • #线程=处理器计数。应用程序可以在标准笔记本电脑(即4个线程)或高端服务器(即是否考虑过异步持久化

      在您的场景中允许这样做吗


      您可以绕过独立线程池中的队列(创建线程池可以避免为每个请求创建(子)线程的开销),在那里,您可以在不影响响应时间的情况下处理合并逻辑。

      从计时来看,结果字典的锁定/构建似乎每个线程需要3700毫秒,而实际处理逻辑只需要300毫秒

      作为一个实验,我建议您让每个线程创建自己的本地结果字典。然后您可以看到,与跨线程锁定的效果相比,构建字典花费了多少时间

      如果构建本地词典的时间超过300毫秒,那么就不可能满足您的时间限制。因为如果不进行任何锁定或尝试合并结果,它已经花费了太长的时间

      更新

      看起来,您可以在进行合并时支付合并费用,锁定导致线程在相当长的时间内处于空闲状态,或者在后处理合并中支付费用。但核心问题是,锁定意味着您没有充分利用可用的CPU

      要从核心获得最大性能,唯一真正的解决方案是使用非阻塞字典实现,它也是线程安全的。我找不到.NET实现,但确实找到了一篇研究论文,详细介绍了一种算法,表明它是可能的

      正确地实现这样一个算法不是一件小事,而是一件有趣的事情


      我们讨论了多少不同的线程,您目前通常会向ConcurrentDictionary添加多少条目?目前通常需要多长时间,需要多快?@PhilWright这是一个很好的观察结果,但是,由于这可能是第一眼看到的问题,我更新了这个问题。@PhilWright,r现在通常需要4秒,但必须低于500秒。如果没有并发字典(即不保存结果:D),它甚至低于300秒。如何处理生成的字典(如果不需要太多的结果,您可以将一些处理延迟到检索数据的后期)?恐怕不允许使用异步存储,因为由于各种原因,当前存储是大量团队工作/协议的结果。数据结构提供内置线程功能和任何自定义操作(例如,一个问题)是通过策略模式传递的。因此,线程池不是一个可能的选项。这是一个很好的观察结果,我记得我在转移到并发集合之前做过这件事。我不记得创建单个字典的开销,但我记得非常昂贵的合并。顺便说一句,输出条目完全取决于操作,可能是10,它是c这将是数十亿美元。谢谢你,这篇论文看起来不错,而且有很多伪代码;-)我试着联系他们,看看是否有任何公开的实现,否则,正如你所说,实现它会很有趣:)而无锁字典是很好的(如果你真的有争议,那么科学是小的或明智的),在这种情况下,进行后处理或只是创建一个主数据结构,提供一个简单的接口来查询n个底层字典(更多的查找时间,但没有复制)应该要快得多。也就是说,最先进的并发无锁字典是Cliff针对java的非阻塞hashmap(还有一篇论文和java one讨论)。这是一个基于状态机的解决方案,允许您实际证明其正确性。移植到c#应该相对简单(如果您使用本机,我至少可以看到一个优化)。如果没有人这样做,我会感到惊讶。