//Функция-нить исполнения //Принимает в виде аргумента контейнер с заданием, //сортирует часть массива //Посылает сообщение в порт static void thread_fun(InputData d, Port<int> resp) { Stopwatch sWatch = new Stopwatch(); sWatch.Start(); qsort(d.array, d.start, d.stop); sWatch.Stop(); Console.WriteLine(d.str+"Время работы: "+ sWatch.ElapsedMilliseconds); resp.Post(1); }
static void task(InputData d, Port<int> resp) { d.result = PerformIntegral(d.start, d.stop, d.n); Console.WriteLine(d.str); Console.WriteLine("Начало: "+d.start+" конец: "+d.stop); Console.WriteLine("Результат на текущем шаге: " + d.result); mRes = mRes + d.result; //формируем общий результат resp.Post(1); }
static void Main(string[] args) { int i; nc = 4;// количество ядер n = 100000000; Arr = new int[n]; int Result = 0; Random r = new Random(); for (int j = 0; j < n; j++) Arr[j] = r.Next(5); System.Diagnostics.Stopwatch sWatch = new System.Diagnostics.Stopwatch(); sWatch.Start(); for (i = 9; i < n; i++)//последовательный алгоритм { Result = Result + Arr[i]; } Console.WriteLine("Сумма:"); Console.WriteLine(Result); sWatch.Stop(); Console.WriteLine("Последовательный алгоритм = {0} мс.", sWatch.ElapsedMilliseconds.ToString()); InputData[] ClArr = new InputData[nc];// создание массива объектов для хранения параметров for (i = 0; i < nc; i++) ClArr[i] = new InputData(); int step = (Int32)(n / nc); // делим количество элементов в массиве на nc частей int c = -1; for (i = 0; i < nc; i++)// заполняем массив параметров { ClArr[i].start = c + 1; ClArr[i].stop = c + step; ClArr[i].i = i; c = c + step; } Dispatcher d = new Dispatcher(nc, "Test Pool"); DispatcherQueue dq = new DispatcherQueue("Test Queue", d); Port<int> p = new Port<int>(); for (i = 0; i < nc; i++) Arbiter.Activate(dq, new Task<InputData, Port<int>>(ClArr[i], p, Sum)); Arbiter.Activate(dq, Arbiter.MultipleItemReceive(true, p, nc, delegate(int[] array) { }));}}}
static void ParPerformInegral(double a, double b, double n) { double a1 = a; double b1 = b; InputData data1 = new InputData(); InputData data2 = new InputData(); data1.str = "Нить исполнения 1"; data1.start = a; data1.stop = b/2+1; data1.n = n; //вместо performInegral(a,b/2+1,n); data2.str = "Нить исполнения 2"; data2.start = b/2+1; data2.stop = b; data2.n = n; //вместо performInegral(b/2+1,b,n); //Создаём диспетчеры с пулом из 2 потоков Dispatcher d = new Dispatcher(2, " Test Pool"); DispatcherQueue dq = new DispatcherQueue(" Test Queue", d); //Описываем (определяем) порт, в который каждый экземпляр метода отправляет сообщение после завершения вычислений Port<int> p = new Port<int>(); //Метод Arbiter.Activate помещает в очередь диспетчера две задачи (два экземпляра метода) //Первый параметр метода Arbiter.Activate – очередь диспетчера, //который будет управлять выполнением задачи, второй параметр – запускаемая задача. Arbiter.Activate(dq, new Task<InputData, Port<int>>(data1, p, task)); Arbiter.Activate(dq, new Task<InputData, Port<int>>(data2, p, task)); return; }
static void Sum(InputData data, Port<int> resp) //параллельный алгоритм { int Result = 0; int i = 0; System.Diagnostics.Stopwatch sWatch = new System.Diagnostics.Stopwatch();//для отсчитывания времени Random r = new Random(); for (int j = 0; j < n; j++) Arr[j] = r.Next(5); sWatch.Start(); for (i = data.start; i <= data.stop; i++) { Result = Result + Arr[i]; //сумма массива } resp.Post(1);//результат отпраляется на порт Console.WriteLine("Поток № {0}: Параллельный алгоритм = {1} мс.", Thread.CurrentThread.ManagedThreadId, sWatch.ElapsedMilliseconds.ToString()); sWatch.Stop(); Console.WriteLine("Сумма:"); Console.WriteLine(Result); }
static void paral_qsort(int[] a, int left, int right) { int l = left; int r = right; int val = 0; int mid = a[(l + r) / 2]; while (l <= r) { while ((a[l] < mid) && (l <= right)) { l++; } while ((a[r] > mid) && (r >= left)) { r--; } if (l <= r) { val = a[l]; a[l] = a[r]; a[r] = val; l++; r--; } } InputData data1 = new InputData(); InputData data2 = new InputData(); if (r > left) { data1.str="Нить исполнения 1"; data1.array = a; data1.start = left; data1.stop = r; //qsort(a, left, r); } if (l < right) { data2.str = "Нить исполнения 2"; data2.array = a; data2.start = l; data2.stop = right; //qsort(a, l, right); } //Создаём диспетчеры Dispatcher d = new Dispatcher(2, " Test Pool"); DispatcherQueue dq = new DispatcherQueue(" Test Queue", d); //Описываем порт Port<int> p = new Port<int>(); Arbiter.Activate(dq, new Task<InputData, Port<int>>(data1, p, thread_fun)); Arbiter.Activate(dq, new Task<InputData, Port<int>>(data2, p, thread_fun)); return; }
//Функция-нить исполнения //Принимает в виде аргумента контейнер с заданием, //сортирует часть массива //Посылает сообщение в порт static void thread_fun(InputData d, Port<int> resp) { qsort(d.array, d.start, d.stop); Console.WriteLine(d.str); resp.Post(1); }
//Метод параллельной сортировки массива static void parral_qsort(int[] a, int left, int right) { //Создаём диспетчеры Dispatcher d = new Dispatcher(2, " Test Pool"); DispatcherQueue dq = new DispatcherQueue(" Test Queue", d); //Описываем порт Port<int> p = new Port<int>(); //Первый этап параллельной сортировки //Параллельно сортируются две половины массива InputData data = new InputData(); data.str = "Первая половина массива "; data.array = a; data.start = 0; data.stop = right/2 + 1; Arbiter.Activate(dq, new Task<InputData, Port<int>>(data, p, thread_fun)); Console.WriteLine("Первый этап"); Console.ReadKey(); data.str = "Вторая половина массива "; data.array = a; data.start = right/2 + 1; data.stop = right; Arbiter.Activate(dq, new Task<InputData, Port<int>>(data, p, thread_fun)); Console.ReadKey(); //Второй этап параллельной сортировки //Сортируется центральная часть массива Console.WriteLine(); Console.WriteLine("Второй этап"); Stopwatch sWatch = new Stopwatch(); sWatch.Start(); qsort(a,right/4,right/4+right/2 +1); sWatch.Stop(); Console.WriteLine("Средняя часть массива Время работы: " + sWatch.ElapsedMilliseconds); Console.ReadKey(); //Третий этап параллельной сортировки //Параллельно сортируются две половины массива data.str = "Первая половина массива "; data.array = a; data.start = 0; data.stop = right / 2 + 1; Arbiter.Activate(dq, new Task<InputData, Port<int>>(data, p, thread_fun)); Console.WriteLine("Первый этап"); Console.ReadKey(); data.str = "Вторая половина массива "; data.array = a; data.start = right / 2 + 1; data.stop = right; Arbiter.Activate(dq, new Task<InputData, Port<int>>(data, p, thread_fun)); Console.ReadKey(); return; }
//параллельная сортирока с нитями исполнения static void paral_qsort(int[] arr_q, int left, int right) { int l = left; int r = right; int temp = 0; int middle = arr_q[(l + r) / 2]; while (l <= r) { while ((arr_q[l] < middle) && (l <= right)) { l++; } while ((arr_q[r] > middle) && (r >= left)) { r--; } if (l <= r) { temp = arr_q[l]; arr_q[l] = arr_q[r]; arr_q[r] = temp; l++; r--; } } InputData data1 = new InputData(); InputData data2 = new InputData(); if (r > left) { data1.str="Нить исполнения 1"; data1.array = arr_q; data1.start = left; data1.stop = r; //вместо qsort(arr_q, left, r); } if (l < right) { data2.str = "Нить исполнения 2"; data2.array = arr_q; data2.start = l; data2.stop = right; //вместо qsort(arr_q, l, right); } //Создаём диспетчеры с пулом из 2 потоков Dispatcher d = new Dispatcher(2, " Test Pool"); DispatcherQueue dq = new DispatcherQueue(" Test Queue", d); //Описываем (определяем) порт, в который каждый экземпляр метода отправляет сообщение после завершения вычислений Port<int> p = new Port<int>(); //Метод Arbiter.Activate помещает в очередь диспетчера две задачи (два экземпляра метода) //Первый параметр метода Arbiter.Activate – очередь диспетчера, //который будет управлять выполнением задачи, второй параметр – запускаемая задача. Arbiter.Activate(dq, new Task<InputData, Port<int>>(data1, p, thread_fun)); Arbiter.Activate(dq, new Task<InputData, Port<int>>(data2, p, thread_fun)); return; }