简体   繁体   中英

How do i use multithreading to speed up code

i have written code to repeat a calculation till it finds the largest number a datatype can hold using this code

            int a = 0;
            int b = 1;
            int c = 0;

            for (int j = 0; j < 10000; j++)
            {
                c = a + b;
                txtOutput.Text = c.ToString();
                a = b;
                b = c;
            }

How would i use the task class or parallelism to make this faster as currently it takes almost 20 minutes to complete this calculation, i need it to happen in 1 minute or less, i tried this code

            Parallel.For(0, 1000000, i =>
            {
                for (int j = 0; j < 10000; j++)
                {
                    c = a + b;
                    txtOutput.Text = c.ToString();
                    a = b;
                    b = c;
                }
            });

But it still takes the same amount of time, i am doing this to learn about multi threading loops for an upcoming project

As The General said, if you touch the UI, you will move your application into a single threaded one.

But there is a thing I don't understand: why do you have to change the content of a text box for each computation? I'm quite sure the data will change so fast that the user won't understand what is happening.

I suggest you to change your code in this way:

  • Put your computation in its own thread, not in the UI one (so not in the "button.click" event if you're working in a WinForm application)
  • Raise an event after about 100 computation, sending the new number as EventArgs
  • Listen for the event and change the UI field when the event is fired

Let us know if it will help you.

Short answer, you can't. Each calculation uses the results of the previous, which means no calculation can start until the previous has finished - your algorithm is synchronous by design. Before you can even try running asynchronously/multithreaded, you need to break up the algorithm into independent segments which you then combine at the end. (note, there are easier ways to boost your performance, not hammering the textbox every iteration is a good start as others have commented). Below is a short example of how you could run an algorithm asyncronously.

Once you have the algorithm broken up into independent segments, you can run it in async mode with Task.Run

 public async Task<ResultType> RunAlgorithm(){
     foreach(var segment in GetSegments()){
          //start processing each segment
          resultTaskList.Add(Task.Run(ProcessSegment(segment)));
     }
     foreach(var resultTask in resultTaskList)
         resultList.Add(await resultTask); //wait for each task to finish processing
     var result = CombineResults(resultList);//combine results to one final result
     return result;
 }
 public ResultType ProcessSegment(SegmentType segment){
     //sync code here
 }
 public List<SegmentType> GetSegments(){
     //break your sample/input data into smaller segments to be processed in parallel
 }
 public ResultType CombineResults(List<ResultType>){
    //take the results of each set of calculations and come up with the overall/total/combined answer
 }

The above code is a fairly minimal example for parallelising a task. its up to you to define a sensible definition for the 'GetSegments' method, the 'ProcessSegment' method and the 'CombineResults' method.

Note, you will threadstarve yourself if you start too many tasks. You can either tune getSegments to return X segments where X is your threadcount. Or you can set it to only run X tasks at a time using some fancy Task.WhenAny calls. I'll give an example of the latter later.

You might also want to make the method signatures very different depending on what works best for your code, this is just a stubbed out example.

Just move the textbox updating outside the loop

    public long SerialCalc(int n)
    {            
        long a = 0, b = 1, c = 0;
        for (int j = 0; j < n; j++)
        {
            c = a + b;
            a = b;
            b = c;
        }
        return c;
    }

and then call it with

    private void button1_Click(object sender, EventArgs e)
    {
        if (int.TryParse(textBox1.Text, out int n) && n>=0)
        {
            textBox2.Clear();
            textBox2.Text = SerialCalc(n).ToString();
        }
    }

This would make it so much faster. In fact your code overflows long several times as it goes past long.MaxValue , becomes negative, goes through zero and past long.MaxValue over and over again.

With a value of 1000000 it takes less than 1 second to finish.

scr1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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