AsParallel () is executed sequentially

I have the following PLINQ request:

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

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

      

I would expect to GetItemsByCustomer()

run in parallel for each client , but it runs sequentially .

I tried to force parallelism but still no luck:

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

      

Method signature:

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

      

According to this article , PLINQ can of course take a sequential route if it deems it appropriate, but forced parallelism should still override this.

Note. This example above is purely illustrative - suppose it customers

is a small list, but GetItemsByCustomer

an expensive method.

+3


source to share


1 answer


There AsParallel()

is nothing wrong with that. It will run as parallel as possible, and there is no serial dependency in your LINQ expression, so there is nothing to make it run sequentially.

A couple of reasons why your code doesn't run in parallel might be:



  • Your box / vm has one cpu or you have a .NET setting to limit parallelism to one cpu. You can simulate it 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 set the parallelism with WithExecutionMode(ParallelExecutionMode.ForceParallelism)

    on one core / CPU or when the degree of parallelism is 1, your setting will have no effect, since true parallelism is not possible.

  • There is some thread blocking for shared resources that happen in your repository. You can simulate thread blocking 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 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();
    
          

  • There are several database options that force queries / reads to be sequential under certain circumstances, and this can give the impression that your C # code is not running in parallel, but in fact it is.

+4


source







All Articles