简体   繁体   English

AsParallel()顺序执行

[英]AsParallel() executing sequentially

I have the following PLINQ query: 我有以下PLINQ查询:

// Let's get a few customers
List<Customer> customers = CustomerRepository.GetSomeCustomers();

// Let's get all of the items for all of these customers
List<CustomerItem> items = customers
    .AsParallel()
    .SelectMany(x => ItemRepository.GetItemsByCustomer(x))
    .ToList();

I would expect GetItemsByCustomer() to be executed in parallel for each customer, but it runs sequentially . 我希望GetItemsByCustomer()将为每个客户并行执行, 但是会顺序运行

I have tried to force parallelism but still without luck: 我试图强制并行化,但是仍然没有运气:

List<CustomerItem> items = customers
    .AsParallel()
    .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
    .SelectMany(x => ItemRepository.GetItemsByCustomer(x))
    .ToList();

The method signature: 方法签名:

private IEnumerable<Item> GetItemsByCustomer(Customer customer)
{
    // Get all items for a customer...
}

According to this article , PLINQ can certainly take the sequential route if it deems fit, but forcing parallelism should still override this. 根据本文 ,如果PLINQ认为合适,当然可以采用顺序路由,但是强制并行性仍应优先于此。

Note: This above example is purely illustrative - assume customers to be a small list and GetItemsByCustomer to be an expensive method. 注意:上面的示例纯粹是示例性的-假设customers是一个很小的列表,而GetItemsByCustomer是一个昂贵的方法。

There is nothing wrong with AsParallel() . AsParallel()没有错。 It will run as parallel if possible, and there is no sequential dependency in your LINQ expression, so there is nothing to force it to run sequentially. 如果可能,它将以并行方式运行,并且LINQ表达式中没有顺序依赖关系,因此没有什么可以强迫它顺序运行。

A couple of reasons why your code doesn't run in parallel could be: 您的代码无法并行运行的几个原因可能是:

  1. Your box/vm has a single CPU or you have a .NET setting to limit the parallelism to one CPU. 您的机器/ VM具有单个CPU,或者具有.NET设置以将并行性限制为一个CPU。 You can Simulate that with this code: 您可以使用以下代码进行模拟:

      var customers = new List<Customer>() { new Customer() {Name = "Mick", Surname = "Jagger"}, new Customer() {Name = "George", Surname = "Clooney"},new Customer() {Name = "Kirk", Surname = "DOuglas"}}; var items = customers .AsParallel() .SelectMany(x => { Console.WriteLine("Requesting: " + x.Name + " - " + DateTime.Now); Thread.Sleep(3000); return new List<CustomerItem>(); }) .WithDegreeOfParallelism(1) .ToList(); 

    Even if you force paralelism with WithExecutionMode(ParallelExecutionMode.ForceParallelism) on a single core/CPU box or when the degree of parallelism is 1, your setting will not have effect, since true parallelism is not possible. 即使您在单个内核/ CPU盒上使用WithExecutionMode(ParallelExecutionMode.ForceParallelism)强制WithExecutionMode(ParallelExecutionMode.ForceParallelism) ,或者当并行度为1时,您的设置也不会生效,因为不可能进行真正的并行化。

  2. There is some thread locking on shared resources happening in your repository. 存储库中发生一些线程锁定共享资源的情况。 You can simulate thread locking with the following code: 您可以使用以下代码模拟线程锁定:

      var customers = new List<Customer>() { new Customer() {Name = "Mick", Surname = "Jagger"}, new Customer() {Name = "George", Surname = "Clooney"},new Customer() {Name = "Kirk", Surname = "DOuglas"}}; var locker = new object(); // Let's get all of the items for all of these customers var items = customers .AsParallel() .SelectMany(x => { lock (locker) { Console.WriteLine("Requesting: " + x.Name + " - " + DateTime.Now); Thread.Sleep(3000); return new List<CustomerItem>(); } }) .ToList(); 
  3. There is some Database setting that is forcing the queries/reads to be sequential under certain circumstances, and that could give you an impression that your C# code is not running in parallel, while it actually is. 在某些情况下,有一些数据库设置会强制查询/读取是连续的,这可能会给您一种印象,即C#代码实际上不是并行运行的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM