Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Parallel in .net

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

Today I will show you how to use Parallel in .net. The content of the article is good. Now I would like to share it with you. Friends who feel in need can understand it. I hope it will be helpful to you. Let's read it along with the editor's ideas.

First, understand hardware threads and software threads

Multi-core processors have more than one physical core-the physical core is a truly independent processing unit, and multiple physical cores enable multiple instructions to run in parallel at the same time. Hardware threads are also known as logical kernels, and a physical kernel can provide multiple hardware threads using hyperthreading technology. So a hardware thread does not represent a physical kernel; every program running in Windows is a process, and each process creates and runs one or more threads, which are called software threads. Hardware threads are like swimming lanes, while software threads are the people who swim in them.

Second, parallel situations

.net Framework4 introduces a new Task Parallel Library (Task parallel Library, TPL), which supports data parallelism, task parallelism, and pipelining. Let developers deal with different parallel situations.

Data parallelism: there is a large amount of data to be processed, and the same operation must be performed on each piece of data. For example, 100 Unicode strings are encrypted by AES algorithm through the key of 256bit.

Task parallelism: running different operations concurrently through tasks. For example, generate file hash codes, encrypt strings, and create thumbnails.

Pipeline: this is a combination of task parallelism and data parallelism.

TPL introduces System.Threading.Tasks, and the main class is Task, which represents an asynchronous and concurrent operation, but we don't have to use an instance of the Task class, we can use the Parallel static class. It provides three methods: Parallel.Invoke and Parallel.For Parallel.Forecah.

III. Parallel.Invoke

The easiest way to try to have many methods run in parallel is to use the Invoke method of the Parallel class. For example, there are four ways:

WatchMovie

HaveDinner

ReadBook

WriteBlog

Parallelism can be used through the following code.

System.Threading.Tasks.Parallel.Invoke (WatchMovie, HaveDinner, ReadBook, WriteBlog)

This code creates a delegate that points to each method. The Invoke method accepts a parameter set of Action.

one

Public static void Invoke (params Action [] actions)

The same effect can be achieved with lambda expressions or anonymous delegates.

System.Threading.Tasks.Parallel.Invoke () = > WatchMovie (), () = > HaveDinner (), () = > ReadBook (), delegate () {WriteBlog ();})

1. There is no specific order of execution.

The Parallel.Invoke method will not return until all four methods have been completed. It requires at least four hardware threads for these four methods to run concurrently. However, there is no guarantee that these four methods can be started and run at the same time, and if one or more kernels are busy, the underlying scheduling logic may delay the initialization of some methods.

Add a delay to the method, and you can see that you have to wait for the longest method execution to complete before returning to the main method.

Static void Main (string [] args) {System.Threading.Tasks.Parallel.Invoke (WatchMovie, HaveDinner, ReadBook, WriteBlog); Console.WriteLine ("execution complete"); Console.ReadKey ();} static void WatchMovie () {Thread.Sleep (5000); Console.WriteLine ("watching a movie") } static void HaveDinner () {Thread.Sleep (1000); Console.WriteLine ("having dinner");} static void ReadBook () {Thread.Sleep (2000); Console.WriteLine ("reading") } static void WriteBlog () {Thread.Sleep (3000); Console.WriteLine ("blog");}

This will cause many logical kernels to be idle for a long time.

IV. Parallel.For

Parallel.For provides load balancing for a fixed number of independent For loop iterations (that is, work is distributed to different tasks so that all tasks can remain busy most of the time) parallel execution. As a result, you can make full use of all available kernels as much as possible.

Let's compare the following two methods, one using a For loop and the other using Parallel.For to generate a key before converting to a hexadecimal string.

Private static void GenerateAESKeys () {var sw = Stopwatch.StartNew (); for (int I = 0; I

< NUM_AES_KEYS; i++) { var aesM = new AesManaged(); aesM.GenerateKey(); byte[] result = aesM.Key; string hexStr = ConverToHexString(result); } Console.WriteLine("AES:"+sw.Elapsed.ToString()); } private static void ParallelGenerateAESKeys() { var sw = Stopwatch.StartNew(); System.Threading.Tasks.Parallel.For(1, NUM_AES_KEYS + 1, (int i) =>

{var aesM = new AesManaged (); aesM.GenerateKey (); byte [] result = aesM.Key; string hexStr = ConverToHexString (result);}); Console.WriteLine ("Parallel_AES:" + sw.Elapsed.ToString ());}

Private static int NUM_AES_KEYS = 100000

Static void Main (string [] args)

{

Console.WriteLine ("execute" + NUM_AES_KEYS+ "times:"); GenerateAESKeys ()

ParallelGenerateAESKeys ()

Console.ReadKey ()

}

Execute 1000000 times

The parallel time here is half that of the serial.

5. Parallel.ForEach

In Parallel.For, optimizing existing loops can sometimes be a very complex task. Parallel.ForEach provides parallel execution of load balancing for a fixed number of independent ForEach loop iterations and supports custom dividers, giving users complete control over data distribution. The essence is to divide all the data to be processed into multiple parts, and then run these serial loops in parallel.

Modify the above code:

System.Threading.Tasks.Parallel.ForEach (Partitioner.Create (1, NUM_AES_KEYS + 1), range = > {var aesM = new AesManaged (); Console.WriteLine ("AES Range ({0}, {1} cycle start time: {2})", range.Item1,range.Item2,DateTime.Now.TimeOfDay); for (int I = range.Item1; I)

< range.Item2; i++) { aesM.GenerateKey(); byte[] result = aesM.Key; string hexStr = ConverToHexString(result); } Console.WriteLine("AES:"+sw.Elapsed.ToString()); }); 从执行结果可以看出,分了13个段执行的。 第二次执行还是13个段。速度上稍微有差异。开始没有指定分区数,Partitioner.Create使用的是内置默认值。 而且我们发现这些分区并不是同时执行的,大致是分了三个时间段执行。而且执行顺序是不同的。总的时间和Parallel.For的方法差不多。 public static ParallelLoopResult ForEach(Partitioner source, Action body) Parallel.ForEach方法定义了source和Body两个参数。source是指分区器。提供了分解为多个分区的数据源。body是 要调用的委托。它接受每一个已定义的分区作为参数。一共有20多个重载,在上面的例子中,分区的类型为Tuple,是一个 二元组类型。此外,返回一个ParallelLoopResult的值。 Partitioner.Create 创建分区是根据逻辑内核数及其他因素决定。 public static OrderablePartitioner Create(int fromInclusive, int toExclusive) { int num = 3; if (toExclusive 再次执行: 分区变成了四个,时间上没有多大差别(***个时间是串行时间)。我们看见这四个分区几乎是同时执行的。大部分情况下,TPL在幕后使用的负载均衡机制都是非常高效的,然而对分区的控制便于使用者对自己的工作负载进行分析,来改进整体的性能。 Parallel.ForEach也能对IEnumerable集合进行重构。Enumerable.Range生产了序列化的数目。但这样就没有上面的分区效果。 private static void ParallelForEachGenerateMD5HasHes() { var sw = Stopwatch.StartNew(); System.Threading.Tasks.Parallel.ForEach(Enumerable.Range(1, NUM_AES_KEYS), number =>

{var md5M = MD5.Create (); byte [] data = Encoding.Unicode.GetBytes (Environment.UserName + number); byte [] result = md5M.ComputeHash (data); string hexString = ConverToHexString (result);}); Console.WriteLine ("MD5:" + sw.Elapsed.ToString ());}

6. Withdraw from the cycle

Unlike break in serial operation, ParallelLoopState provides two methods to stop the execution of Parallel.For and Parallel.ForEach.

Break: causes the loop to stop execution as soon as possible after the current iteration. For example, when 100 is executed, the loop will process all iterations less than 100.

Stop: let the loop stop execution as soon as possible. If 100 iterations are performed, there is no guarantee that all iterations less than 100 will be processed.

Modify the above method: exit after 3 seconds.

Private static void ParallelLoopResult (ParallelLoopResult loopResult) {string text; if (loopResult.IsCompleted) {text = "loop complete";} else {if (loopResult.LowestBreakIteration.HasValue) {text = "Break termination" } else {text = "Stop termination";}} Console.WriteLine (text);} private static void ParallelForEachGenerateMD5HasHesBreak () {var sw = Stopwatch.StartNew () Var loopresult= System.Threading.Tasks.Parallel.ForEach (Enumerable.Range (1, NUM_AES_KEYS), (int number,ParallelLoopState loopState) = > {var md5M = MD5.Create (); byte [] data = Encoding.Unicode.GetBytes (Environment.UserName + number); byte [] result= md5M.ComputeHash (data); string hexString = ConverToHexString (result)) If (sw.Elapsed.Seconds > 3) {loopState.Stop ();}}); ParallelLoopResult (loopresult); Console.WriteLine ("MD5:" + sw.Elapsed);}

Catch exceptions that occur in parallel loops.

When a delegate called in a parallel iteration throws an exception that is not caught in the delegate, it becomes a set of exceptions that the new System.AggregateException handles.

Private static void ParallelForEachGenerateMD5HasHesException () {var sw = Stopwatch.StartNew (); var loopresult = new ParallelLoopResult (); try {loopresult = System.Threading.Tasks.Parallel.ForEach (Enumerable.Range (1, NUM_AES_KEYS), (number, loopState) = > {var md5M = MD5.Create () Byte [] data = Encoding.Unicode.GetBytes (Environment.UserName + number); byte [] result = md5M.ComputeHash (data); string hexString = ConverToHexString (result); if (sw.Elapsed.Seconds > 3) {throw new TimeoutException ("execute for more than three seconds") }});} catch (AggregateException ex) {foreach (var innerEx in ex.InnerExceptions) {Console.WriteLine (innerEx.ToString ()) }} ParallelLoopResult (loopresult); Console.WriteLine ("MD5:" + sw.Elapsed);}

Results:

The anomaly occurred several times.

Specify the degree of parallelism.

TPL's approach always tries to use all available logical kernels to achieve * results, but sometimes you don't want to use all kernels in parallel loops. For example, you need to set aside a kernel that does not participate in parallel computing to create applications that respond to users, and this kernel needs to help you run the rest of the code. A good solution at this time is to specify the degree of parallelism.

This requires creating an instance of ParallelOptions and setting the value of MaxDegreeOfParallelism.

Private static void ParallelMaxDegree (int maxDegree) {var parallelOptions = new ParallelOptions (); parallelOptions.MaxDegreeOfParallelism = maxDegree; var sw = Stopwatch.StartNew (); System.Threading.Tasks.Parallel.For (1, NUM_AES_KEYS + 1, parallelOptions, (int I) = > {var aesM = new AesManaged (); aesM.GenerateKey () Byte [] result = aesM.Key; string hexStr = ConverToHexString (result);}); Console.WriteLine ("AES:" + sw.Elapsed.ToString ());}

Call: if you run on a quad-core microprocessor, three cores will be used.

ParallelMaxDegree (Environment.ProcessorCount-1)

It's a bit slow in time (the first Parallel.For 3.18s), but you can free up a kernel to handle other things.

This is all about how to use Parallel in .net. For more content related to how to use Parallel in .net, you can search for previous articles or browse the following articles to learn! I believe the editor will add more knowledge to you. I hope you can support it!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report