none
parallel foreach is slower than old fashion multithreading.

    Question

  • Hello,

    I have 2 threading code, I believe similar work they do. but first approach with old classic threading works faster that using parallel foreach. why is that? 
    Second problem is my executeThread() function does multiple webservice calls and when i have timeout 30secs for my cancellation token, it doesnt finish threading in 30secs.
    it reaches sometimes 40secs althought first thread approach aborts in 30secs. 

    PS: I know thread.abort is not something good and efficient but this is other issue, not my question.

    thanks for your answers
      

    For Each myavailableItem In myItemList
                Thread = New Thread(New ParameterizedThreadStart(AddressOf executeThread))
                Thread.IsBackground = True
                Thread.Name = myavailableItem
                Thread.Start(myavailableItem)
                Threads.Add(Thread)
              Next
    
              ' Continue this Loop checking if any thread is still alive or timeout has occured
              ' If all thread have been completed or the master timeout has occured continue
              Do While (Now - start).TotalSeconds < timeOut And livingThreadsCount > 0
                livingThreadsCount = 0
    
                For Each processedThread As Thread In Threads
                  If (processedThread.IsAlive) Then
                    livingThreadsCount += 1
                  End If
                Next
    
                Thread.Sleep(100)
              Loop
    
              ' After Timeout abort all threads if they are still alive
              If (livingThreadsCount > 0) Then
                For Each processedThread As Thread In Threads
                  If (processedThread.IsAlive) Then
                    processedThread.Abort()
                  End If
                Next
              End If
    

     

    Parallel foreach

     

     Using mytimer = New Timer(Sub() cts.Cancel(), Nothing, timeout, -1)
            Try
              Parallel.ForEach(myItems, myoptions, Sub(myItem As Item, loopstate As ParallelLoopState)
                                         '' Try
                                         If myoptions.CancellationToken.IsCancellationRequested = True Then
                                           ' loopstate.Stop()
                                           cts.Cancel()
                                           Exit Sub
                                         Else
    
    																		 'function doing process
                                         Call executeThread()
    
                                         End If
                                       End Sub)
            Catch ex As Exception
            
            End Try
          End Using

    "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
    • Edited by emil_tr Thursday, September 08, 2011 2:22 PM
    Thursday, September 08, 2011 2:21 PM

Answers

  • Sorry for not answering. I was in holliday :)

    Question 1:

    You can use ThreadPool.SetMinThreads and ThreadPool.SetMaxThreads to control how many threads you will have. When using SetMinThreads, immediately the given amount of worker threads will be created. it does not have to be done later. 

    Environment.ProcessorCount
    

     will help you to set the amount of threads, you want to have per core.

    Question 2:

    Sorry, I know C# and Pararllel, but not IIS.

     

    The blocking threads are the reason, why you need many of them. As long as a thread is blocking by waiting on a webcall, its processor is doing nothing. Then you have to start a new thread. Having a big amount of workerthreads, which were created in the very past will solve the problem, because threads doesn't have to be started when calculations starts.

    Cancelation is always done like you did: if "token.isCancelationRequired".... what you can do, is to give that token to your executeThread-method and ask that token many times. But finally, that will not help with the problem, that your webservice calls are blocking a long long time, up to 15s. You will always have to wait these 15s for cancelation, if you are using blocking threads.

    If you don't want to wait these 15s, then you are not allowed to use blocking threads. Or you have to use Thread.Abort() or Thread.Interupt(), which should be avoided. What you may search for is, how to make a async-call on a webservice. One of your workerthreads can make a async call to a webservice and then, is is not blocking. The async-call to the webservice will alert as soon as the answer arrives. This will usually happen in its own thread, in a workerthread or by a waithandle.

    In this case your executeThread would be programmed in many things:

    - First method is doing something before the webcall and then is starting the webcall

    - Somewhere, there is an internal webservice-.Net-Async-call queue, for all the waiting methdocalls.

    - The second Method is called, as soon as a webservice is responding, to evaluate the data.

    Tuesday, September 20, 2011 9:52 AM

All replies

  • First Problem:

    Keep in mind, that the parallel-library is working with the Threadpool. It only works on that many threads in parallel, that are needed to get the processor load to 100%.

    Let's make a little calculation to explan: Imagine you need 30s to excute "executeThread" for one element in the list. You have four processors and 5 elements in the list:

    Doing it with your "old-fashion-method":  5 item * 30seconds / 4 processors = 37,5 seconds plus time for switching threads

    Doing it with TPL: 4 items * 30 seconds / 4 processors + 1 lastitem with one processor = 60s without switching threads.

    As you can see, the speed depends on what you are doing. your execute takes long and does make many webcalls. I propose you to split this method in many tasks (i.e. one taks for each call) and then use a http://msdn.microsoft.com/de-de/library/dd267312.aspx (System.Collections.Concurrent.BlockingCollection) to accomplish a pipeline.

     

    Second problem:

    You check the cancelationtoken before you call executeThread. If executeThread is started, it will finish and you have to wait for it! Only the executeThreads, which aren't started yet, will close... If you use my proposal from abough, then you can put a cancelationtoken in every task, then there aren't that many things which have to be completed before finishing.

     

    Thursday, September 08, 2011 3:05 PM
  • Hi GreatVolk

      i'm looking at your calculations:

    Doing it with your "old-fashion-method":  5 item * 30seconds / 4 processors = 37,5 seconds plus time for switching threads

    Doing it with TPL: 4 items * 30 seconds / 4 processors + 1 lastitem with one processor = 60s without switching threads.


    and i can't undestand because if we assume to have 100 items and and execution time of 5 seconds for each item wi will have:

     

    Doing it with your "old-fashion-method":  100 items * 5 seconds / 4 processors = 125 seconds plus time for switching threads
     
    Doing it with TPL: 99 items * 5 seconds / 4 processors + 1 lastitem with one processor = 128s without switching threads.

     

    So there will not be performance improvements... i feel a bit confused...


    GP
    Friday, September 09, 2011 7:52 AM
  • Doing it with TPL: 99 items * 5 seconds / 4 processors + 1 lastitem with one processor = 128s without switching threads.

    So there will not be performance improvements... i feel a bit confused...


    GP


    emil_tr didn't tell us, how many items he has to calculate. He also didn't tell us, how much jitter his single calculations have. He also didn't tell us how much time is waisted by a executeThread-Method i.e. into waiting for a webservice. These are all important thing, one have to know, when analysing, why the Parallel foreach is slower than his "I raise a thread for every executeThread I have" (IratfeeTIh).

    You are right, having a 100 items, wouldn't make a difference between the two approachs from emil_tr. Having 5 would/could make a big difference. Why: If you are using emil_tr's IratfeeTIh-method, then all executeThreads are working in parallel and all are probably finished at the same time. Using Parallel means, exact four (the number of processors) items are handled at the same time, then you have one rest. This one element is calculated with one processor, the other three processors are waised. Having 100 items, means, that waisting three processors for one calculation time isn't relevant... and 100 can be devided by 4, so it may not happen, that any processor time is waisted. (Which means you even got 125s in your calculations). :) I picked one possible assumption and explained it. You are right, the assumption can be wrong.

    Another assumption: He's having 100 items, but the executeThreads are doing waiting most of the time. Then the following would happen: Each 200ms the Parallel-Task-Manager inside .Net recognizes, that all threads he has are working, but the processors are not used with 100%. What's he doing? He is starting a new Workerthread. Then 200ms later, he is recognizing the same problem, starting a new Workerthread.... Much time is lost until enough threads are started to use the processors with 100%. What may then help:

    a) a cool pipeline (as I already mentioned ;) )

    b) using

    ThreadPool.SetMinThreads(bignumber);
    

     to increase the number of working threads at the beginning.

    Friday, September 09, 2011 8:37 AM
  • I actually have 20 web services to be requested and each of them has its response time.

    response times vary between 1 secs min. to 15secs maximum. 

    using first threading approach I am depending on slowest web service but second approach is mostly like more than slowest web service. 

    Executethread is the function calling each web services by select case. 

    @GreatVolk: I would like to try the approach in your article but could you tell me how I can handle cancellation with timeout by using that task.factory?

     

    thanks a lot


    "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
    • Edited by emil_tr Monday, September 12, 2011 7:58 AM
    Monday, September 12, 2011 7:57 AM
  • I have just 2 following questions regarding my quesiton.

    1) can I control and set how many threads per core or process can be run?

    2) when I right click on my project in IIS and under properties/performace  tab there is a set up called

    "max number of worker processes". it has default 1. how that affects my threading if I increase that?

    thanks for your help agian.


    "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
    Monday, September 19, 2011 2:49 PM
  • Sorry for not answering. I was in holliday :)

    Question 1:

    You can use ThreadPool.SetMinThreads and ThreadPool.SetMaxThreads to control how many threads you will have. When using SetMinThreads, immediately the given amount of worker threads will be created. it does not have to be done later. 

    Environment.ProcessorCount
    

     will help you to set the amount of threads, you want to have per core.

    Question 2:

    Sorry, I know C# and Pararllel, but not IIS.

     

    The blocking threads are the reason, why you need many of them. As long as a thread is blocking by waiting on a webcall, its processor is doing nothing. Then you have to start a new thread. Having a big amount of workerthreads, which were created in the very past will solve the problem, because threads doesn't have to be started when calculations starts.

    Cancelation is always done like you did: if "token.isCancelationRequired".... what you can do, is to give that token to your executeThread-method and ask that token many times. But finally, that will not help with the problem, that your webservice calls are blocking a long long time, up to 15s. You will always have to wait these 15s for cancelation, if you are using blocking threads.

    If you don't want to wait these 15s, then you are not allowed to use blocking threads. Or you have to use Thread.Abort() or Thread.Interupt(), which should be avoided. What you may search for is, how to make a async-call on a webservice. One of your workerthreads can make a async call to a webservice and then, is is not blocking. The async-call to the webservice will alert as soon as the answer arrives. This will usually happen in its own thread, in a workerthread or by a waithandle.

    In this case your executeThread would be programmed in many things:

    - First method is doing something before the webcall and then is starting the webcall

    - Somewhere, there is an internal webservice-.Net-Async-call queue, for all the waiting methdocalls.

    - The second Method is called, as soon as a webservice is responding, to evaluate the data.

    Tuesday, September 20, 2011 9:52 AM