Параллельное программирование - C#

Узнай цену своей работы

Формулировка задачи:

Решил накидать простенькую задачу: выполнить какие-нибудь операции над большим блоком данных. И это все распараллелить. Это можно сделать 2мя способами: 1. Параллелить вызов коротеньких процедур. Но тогда будет очень много времени тратиться на то, чтобы передать управление другому ядру. Ведь так? ну нет смысла параллелить операцию 2+2. 2. Параллелить обработку блоков данных. Логично предположить. что когда параллельно запускаться будут тяжелые процедуруы, эффект от параллельности будет гораздо выше. Однако оказались весьма странные результаты. Почему-то первоначальный эффект от параллельности отрицательный. Вот код простой программки, которая наглядно всё демонстрирует:
Листинг программы
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using System.Diagnostics;
  11. using System.Threading;
  12. namespace WindowsFormsApplication2
  13. {
  14. public partial class Form1 : Form
  15. {
  16. public Form1()
  17. {
  18. InitializeComponent();
  19. }
  20. double [] _dArray = new double[10000000];
  21. double[] _dArray2 = new double[10000000];
  22. int _iThreads = 8;
  23. int _iSizeBlock;
  24. private void button1_Click(object sender, EventArgs e)
  25. {
  26. _iSizeBlock = _dArray.Length / _iThreads;//размер блока
  27. //заполним массив случайно
  28. Random r = new Random();
  29. for (int i = 0; i < _dArray.Length; i++)
  30. {
  31. _dArray[i] = r.NextDouble();
  32. _dArray2[i] = _dArray[i];
  33. }
  34. richTextBox1.Text = "1 итерация:\r\n";
  35. for (int i = 1; i <= 8; i++)
  36. {
  37. ParallelOptions options = new ParallelOptions
  38. {
  39. MaxDegreeOfParallelism = i
  40. };
  41. Stopwatch st1 = new Stopwatch();
  42. st1.Start();
  43. Parallel.For(0, _dArray.Length, options, parallelOne);
  44. st1.Stop();
  45. richTextBox1.Text += i.ToString() + " поток, время: " + st1.Elapsed.TotalSeconds.ToString() + "\r\n";
  46. }
  47. richTextBox1.Text += "Блок итераций:\r\n";
  48. for (int i = 1; i <= 8; i++)
  49. {
  50. ParallelOptions options = new ParallelOptions
  51. {
  52. MaxDegreeOfParallelism = i
  53. };
  54. Stopwatch st1 = new Stopwatch();
  55. st1.Start();
  56. Parallel.For(0, i, options, ParallelBlock);
  57. st1.Stop();
  58. richTextBox1.Text += i.ToString() + " поток, время: " + st1.Elapsed.TotalSeconds.ToString() + "\r\n";
  59. }
  60. }
  61. private void ParallelBlock(int iIndex)
  62. {
  63. int iStart = iIndex * _iSizeBlock;
  64. int iEnd = iStart + _iSizeBlock;
  65. //iIndex - номер блока
  66. for (int i = iStart; i < iEnd; i++)
  67. {
  68. _dArray[i] = Someoperations(_dArray[i]);
  69. }
  70. }
  71. private void parallelOne(int iIndex)
  72. {
  73. _dArray[iIndex] = Someoperations(_dArray[iIndex]);
  74. }
  75. private double Someoperations(double dInput)
  76. {
  77. double Result = Math.Sin(dInput) * Math.Log(dInput + 10);
  78. Result = Math.Pow(Result, 10);
  79. Result += Math.Abs(Math.Cos(Result));
  80. Result += Math.Sqrt(Result);
  81. Result = Math.Pow(Result, 2);
  82. return Result;
  83. }
  84. }
  85. }
А вот результат. 1 итерация: 1 поток, время: 2,5947303 2 поток, время: 1,5046816 3 поток, время: 1,2435103 4 поток, время: 1,1743574 5 поток, время: 1,8177255 6 поток, время: 1,8564871 7 поток, время: 1,7038264 8 поток, время: 1,7404472 Блок итераций: 1 поток, время: 1,2824387 2 поток, время: 1,2592897 3 поток, время: 1,3303499 4 поток, время: 1,3710368 5 поток, время: 1,4195757 6 поток, время: 1,4460356 7 поток, время: 1,5213963 8 поток, время: 1,6072681 Как видно, во втором случае результат очень плохой. То есть распараллеливание медленно отрабатывает. Почему так? Ведь по логике второй способ распараллеливания должен быть лучше первого?

Решение задачи: «Параллельное программирование»

textual
Листинг программы
  1. public OneObject(Image<Lab, byte> imgSource,//исходное изображение
  2.             Image<Bgr, byte> imgBinarized,//бинаризованное изображение
  3.             Rectangle rect//область объекта
  4.  
  5.             )
  6.         {
  7.             watchSegmentation = new Stopwatch();
  8.             int iStopY = rect.Y + rect.Height;
  9.             int iStopX = rect.X + rect.Width;
  10.             _iObjectpixels = 0;
  11.             //узнать число пикселей объекта (по бинаризованному изображению)
  12.             for (int y = rect.Y; y < iStopY; y++)
  13.             {
  14.                 for (int x = rect.X; x < iStopX; x++)
  15.                 {
  16.                     if ((imgBinarized.Data[y, x, 0] < 123) && (imgBinarized.Data[y, x, 1] < 123) && (imgBinarized.Data[y, x, 2] < 123))
  17.                     {
  18.                         _iObjectpixels++;
  19.                     }
  20.                 }
  21.             }
  22.             //поместить в матрицу пиксели объекта
  23.             matrSourceObject = new Matrix<float>(_iObjectpixels, 1, 3);
  24.             matrClusteredObject = new Matrix<int>(_iObjectpixels, 1);
  25.  
  26.  
  27.             int iObjectpixels = 0;
  28.             //заполнить матрицу изображениями объекта без фона
  29.             for (int y = rect.Y; y < iStopY; y++)
  30.             {
  31.                 for (int x = rect.X; x < iStopX; x++)
  32.                 {
  33.                     if ((imgBinarized.Data[y, x, 0] < 123) && (imgBinarized.Data[y, x, 1] < 123) && (imgBinarized.Data[y, x, 2] < 123))
  34.                     {
  35.                         matrSourceObject.Data[iObjectpixels, 0] = (float)imgSource[y, x].X;
  36.                         matrSourceObject.Data[iObjectpixels, 1] = (float)imgSource[y, x].Y;
  37.                         matrSourceObject.Data[iObjectpixels, 2] = (float)imgSource[y, x].Z;
  38.                         iObjectpixels++;
  39.                     }
  40.                 }
  41.             }
  42.  
  43.             MCvTermCriteria term = new MCvTermCriteria(50, 0.9);
  44.             term.Type = TermCritType.Eps | TermCritType.Iter;
  45.  
  46.             clusterCount = 2;
  47.             int attempts = 5;
  48.             Matrix<Single> centers = new Matrix<Single>(clusterCount, imgSource.Rows * imgSource.Cols);
  49.             //сегментация
  50.             //еще нужно будет в цикле определять число кластеров
  51.             //но это потом
  52.             double divLastStep = 0, divThisStep = 0, dLastSterpEntr = 0;
  53.             double dEntropy = 0;
  54.             bool bEntrStop = false;
  55.             bool bSKOStop = false;
  56.             List<double> listDobleEntropy = new List<double>();
  57.             List<double> listDoubleSKOMult = new List<double>();
  58.             watchSegmentation.Restart();
  59.            
  60.             while (true)
  61.             {
  62.                 listMatr.Clear();
  63.                
  64.                 try
  65.                 {
  66.                     watchSegmentation.Start();
  67.                     CvInvoke.Kmeans(matrSourceObject, clusterCount, matrClusteredObject, term, attempts, KMeansInitType.PPCenters, centers);
  68.                     watchSegmentation.Stop();
  69.                 }
  70.                 catch
  71.                 {
  72.                     clusterCount--;
  73.                     listMatr.Clear();
  74.                     CvInvoke.Kmeans(matrSourceObject, clusterCount, matrClusteredObject, term, attempts, KMeansInitType.PPCenters, centers);
  75.                     //поместить все точки объекта в текущею ячейку, в которой будет список из сегментов, в каждом из которых содержатся точки
  76.                     MyClass.pointsIntoListClusters(matrSourceObject, matrClusteredObject, listMatr, clusterCount);
  77.                     break;
  78.                 }
  79.                
  80.                 //поместить все точки объекта в текущею ячейку, в которой будет список из сегментов, в каждом из которых содержатся точки
  81.                 MyClass.pointsIntoListClusters(matrSourceObject, matrClusteredObject, listMatr, clusterCount);
  82.  
  83.                 //определяем максимальную энтропию по всем кластерам
  84.                 listDobleEntropy.Clear();
  85.                 listDoubleSKOMult.Clear();
  86.                 //watchSegmentation.Start();
  87.                 listDobleEntropy = MyMath.GetEntropyInAllClusters(listMatr);
  88.                 //watchSegmentation.Start();
  89.                 dEntropy = MyMath.Max(listDobleEntropy);
  90.                 //проверка критерия останова по энтропии
  91.                 if (dEntropy < dLastSterpEntr)
  92.                 {
  93.                     bEntrStop = true;
  94.                 }
  95.                 //определяем произведение СКО компонент для каждого кластера
  96.                 double[] dSKOMult = new double[clusterCount];
  97.                 for (int i = 0; i < clusterCount; i++)
  98.                 {
  99.                     dSKOMult[i] = 1;
  100.                     dSKOMult[i] *= MyMath.GetMeanSquareDiviation(listMatr[i], 0);
  101.                     dSKOMult[i] *= MyMath.GetMeanSquareDiviation(listMatr[i], 1);
  102.                     dSKOMult[i] *= MyMath.GetMeanSquareDiviation(listMatr[i], 2);
  103.                 }
  104.  
  105.                 divThisStep = MyMath.Max(dSKOMult) / MyMath.Min(dSKOMult);
  106.                 if (divThisStep < divLastStep)
  107.                 {
  108.                     bSKOStop = true;
  109.                 }
  110.  
  111.  
  112.                 //условие выхода из цикла
  113.                 if ((bSKOStop && bEntrStop) || (clusterCount >= 9))
  114.                 {
  115.                     clusterCount++;
  116.                     watchSegmentation.Start();
  117.                     try
  118.                     {
  119.                         listMatr.Clear();
  120.                         CvInvoke.Kmeans(matrSourceObject, clusterCount, matrClusteredObject, term, attempts, KMeansInitType.PPCenters, centers);
  121.                        
  122.                        
  123.                     }
  124.                     catch
  125.                     {
  126.                         listMatr.Clear();
  127.                         clusterCount--;
  128.                         CvInvoke.Kmeans(matrSourceObject, clusterCount, matrClusteredObject, term, attempts, KMeansInitType.PPCenters, centers);
  129.                         //поместить все точки объекта в текущею ячейку, в которой будет список из сегментов, в каждом из которых содержатся точки              
  130.                     }
  131.                     finally
  132.                     {
  133.                         MyClass.pointsIntoListClusters(matrSourceObject, matrClusteredObject, listMatr, clusterCount);
  134.                     }
  135.                     watchSegmentation.Stop();
  136.                     break;
  137.                 }
  138.  
  139.                 divLastStep = divThisStep;
  140.                 dLastSterpEntr = MyMath.Max(listDobleEntropy);
  141.  
  142.                 clusterCount++;
  143.                
  144.             }
  145.  
  146.             iSegmentsInObject = clusterCount;
  147.  
  148.  
  149.             //вывод результата в красивой картинке
  150.             imgSegmentedObject = new Image<Bgr, byte>(new System.Drawing.Size(rect.Width, rect.Height));
  151.             imgObject = new Image<Lab, byte>(new System.Drawing.Size(rect.Width, rect.Height));
  152.  
  153.             iObjectpixels = 0;
  154.             int iColorNumber = 0;
  155.             int iy = 0;
  156.             for (int y = rect.Y; y < iStopY; y++)
  157.             {
  158.  
  159.                 int ix = 0;
  160.  
  161.                 for (int x = rect.X; x < iStopX; x++)
  162.                 {
  163.  
  164.                     if ((imgBinarized.Data[y, x, 0] < 123) && (imgBinarized.Data[y, x, 1] < 123) && (imgBinarized.Data[y, x, 2] < 123))
  165.                     {
  166.                         iColorNumber = matrClusteredObject.Data[iObjectpixels, 0];
  167.                         imgSegmentedObject.Data[iy, ix, 0] = (byte)clusterColors[iColorNumber].Red;
  168.                         imgSegmentedObject.Data[iy, ix, 1] = (byte)clusterColors[iColorNumber].Green;
  169.                         imgSegmentedObject.Data[iy, ix, 2] = (byte)clusterColors[iColorNumber].Blue;
  170.  
  171.                         imgObject.Data[iy, ix, 0] = (byte)matrSourceObject.Data[iObjectpixels, 0];
  172.                         imgObject.Data[iy, ix, 1] = (byte)matrSourceObject.Data[iObjectpixels, 1];
  173.                         imgObject.Data[iy, ix, 2] = (byte)matrSourceObject.Data[iObjectpixels, 2];
  174.  
  175.                         iObjectpixels++;
  176.  
  177.                     }
  178.                     else
  179.                     {
  180.                         imgSegmentedObject.Data[iy, ix, 0] = 255;
  181.                         imgSegmentedObject.Data[iy, ix, 1] = 255;
  182.                         imgSegmentedObject.Data[iy, ix, 2] = 255;
  183.  
  184.                         imgObject.Data[iy, ix, 0] = 255;
  185.                         imgObject.Data[iy, ix, 1] = 125;
  186.                         imgObject.Data[iy, ix, 2] = 125;
  187.  
  188.                     }
  189.                     ix++;
  190.                 }
  191.                 iy++;
  192.             }
  193.         }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы