I decided to throw a simple task: perform some operations on a large data block. And this is all parallelized. This can be done in two ways: 1. Parallel call a short procedure. But then there will be a lot of time spent on transferring control to another kernel. It is so? Well, it makes no sense to parallelize the operation 2 + 2. 2. Parallel processing of data blocks. It is logical to assume. that when parallel procedures run will be difficult, the effect of parallelism will be much higher. However, there were very strange results. For some reason, the initial effect of parallelism is negative. Here is the code for a simple program that demonstrates everything clearly:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Diagnostics; using System.Threading; namespace WindowsFormsApplication2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } double [] _dArray = new double[10000000]; double[] _dArray2 = new double[10000000]; int _iThreads = 8; int _iSizeBlock; private void button1_Click(object sender, EventArgs e) { _iSizeBlock = _dArray.Length / _iThreads;//ΡΠ°Π·ΠΌΠ΅Ρ Π±Π»ΠΎΠΊΠ° //Π·Π°ΠΏΠΎΠ»Π½ΠΈΠΌ ΠΌΠ°ΡΡΠΈΠ² ΡΠ»ΡΡΠ°ΠΉΠ½ΠΎ Random r = new Random(); for (int i = 0; i < _dArray.Length; i++) { _dArray[i] = r.NextDouble(); _dArray2[i] = _dArray[i]; } richTextBox1.Text = "1 ΠΈΡΠ΅ΡΠ°ΡΠΈΡ:\r\n"; for (int i = 1; i <= 8; i++) { ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = i }; Stopwatch st1 = new Stopwatch(); st1.Start(); Parallel.For(0, _dArray.Length, options, parallelOne); st1.Stop(); richTextBox1.Text += i.ToString() + " ΠΏΠΎΡΠΎΠΊ, Π²ΡΠ΅ΠΌΡ: " + st1.Elapsed.TotalSeconds.ToString() + "\r\n"; } richTextBox1.Text += "ΠΠ»ΠΎΠΊ ΠΈΡΠ΅ΡΠ°ΡΠΈΠΉ:\r\n"; for (int i = 1; i <= 8; i++) { ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = i }; Stopwatch st1 = new Stopwatch(); st1.Start(); Parallel.For(0, i, options, ParallelBlock); st1.Stop(); richTextBox1.Text += i.ToString() + " ΠΏΠΎΡΠΎΠΊ, Π²ΡΠ΅ΠΌΡ: " + st1.Elapsed.TotalSeconds.ToString() + "\r\n"; } } private void ParallelBlock(int iIndex) { int iStart = iIndex * _iSizeBlock; int iEnd = iStart + _iSizeBlock; //iIndex - Π½ΠΎΠΌΠ΅Ρ Π±Π»ΠΎΠΊΠ° for (int i = iStart; i < iEnd; i++) { _dArray[i] = Someoperations(_dArray[i]); } } private void parallelOne(int iIndex) { _dArray[iIndex] = Someoperations(_dArray[iIndex]); } private double Someoperations(double dInput) { double Result = Math.Sin(dInput) * Math.Log(dInput + 10); Result = Math.Pow(Result, 10); Result += Math.Abs(Math.Cos(Result)); Result += Math.Sqrt(Result); Result = Math.Pow(Result, 2); return Result; } } } And here is the result.
1 iteration:
1 stream, time: 2.5947303
2 stream time: 1,5046816
3 stream time: 1.2435103
4 stream time: 1,1743574
5 stream time: 1.8177255
6 stream time: 1.8564871
7 stream, time: 1,7038264
8 stream time: 1,7404472
Block iterations:
1 stream, time: 1,2824387
2 stream time: 1.2592897
3 stream time: 1,3303499
4 stream time: 1.3710368
5 stream time: 1.4195757
6 stream time: 1.4460356
7 stream time: 1.5213963
8 stream, time: 1.6072681
As you can see, in the second case, the result is very bad. That is, paralleling slowly works. Why is that? After all, logically, the second way of parallelization should be better than the first? I found this on the Internet.
Thread.BeginThreadAffinity(); foreach(ProcessThread pt in Process.GetCurrentProcess().Threads) { int utid = GetCurrentThreadId(); if (utid == pt.Id) { pt.ProcessorAffinity = (IntPtr)(_iCPUThread); // Set affinity for this AllIterations(); } } Thread.EndThreadAffinity(); Maybe this way you can somehow more optimally solve my problem and the code will speed up? Can you tell? And then something like a dead end. Is it possible to parallelize the code that I wrote above using the example given above by me? The main difficulty lies in passing the index to the stream. After all, I process the array by index. Thank you.
Thread.BeginThreadAffinitydoes the wrong thing. It nails logical thread to the system thread. This is actually not necessary at the moment, since in almost all implementations of the CLR, managed thread is implemented using the system thread. - VladD