Опубликован: 23.04.2013 | Уровень: для всех | Доступ: платный
Лекция 5:

Потоки и параллельные вычисления

< Лекция 4 || Лекция 5: 1234 || Лекция 6 >

Быстрая сортировка Хоора и потоки

Введение потоков в алгоритм быстрой сортировки позволит продемонстрировать еще один прием работы с потоками, отличный от применяемого при пузырьковой сортировке. Дело в том, что быстрая сортировка представляет рекурсивную процедуру, для которой передача параметров обязательна. По этой причине, метод, передаваемый потоку в момент его создания должен иметь параметры. Технология работы с потоками разрешает методу иметь параметры, но параметр должен быть только один универсального типа object.

Чтобы удовлетворить технологическим требованиям, введем структуру, описывающую параметры, требуемые методу сортировки:

struct StructOne
    {
        public double[] mas;        
        public int n;
        public int start, finish;
        public StructOne(double[] mas, int start, int finish)
        {
            this.mas = mas;
            this.start = start;
            this.finish = finish;
            n = mas.Length;
        }
    }

Рассмотрим теперь версию параллельного алгоритма, работающего с потоками:

public void QSortWithTreads(double[] mas, int p)
        {
            Thread[] threads = new Thread[p];
            StructOne[] sorts = new StructOne[p];
            int start = 0, finish = 0, n = mas.Length, m = n/p;
            for (int i = 0; i < p; i++)
            {
                start = i * m;
                finish = i != p - 1 ? start + m - 1 : n - 1;
                sorts[i] = new StructOne(mas, start, finish);
                threads[i] = new Thread(QSortStruc);
                threads[i].Start(sorts[i]);
            }
            for (int i = 0; i < p; i++)
            {
                threads[i].Join();
            }
            //Слияние отсортированных последовательностей
            MergeQ(mas, p);
        }

Как можно видеть, при создании потока ему не передается экземпляр некоторого класса. Всем потокам передается один и тот же метод QSortStruc, но параметр, передаваемый потоку, у каждого потока свой, что гарантирует корректное распараллеливание по данным.

Метод QSortStruc представляет собой слегка модифицированную версию классического алгоритма быстрой сортировки:

void QSortStruc(object param)
        {
            StructOne s = (StructOne)param; 
            double[] mas = s.mas;
            int start = s.start;
            int finish = s.finish;
            int n = s.n;
            if (finish - start > 0)
            {
                double cand = 0, temp = 0;
                int l = start, r = finish;
                cand = mas[(r + l) / 2];
                while (l <= r)
                {
                    while (mas[l] < cand) l++;
                    while (mas[r] > cand) r--;
                    if (l <= r)
                    {
                        temp = mas[l];
                        mas[l] = mas[r];
                        mas[r] = temp;
                        l++; r--;
                    }
                }
                StructOne left = new StructOne(mas, start, r);
                QSortStruc(left);
                StructOne right = new StructOne(mas, l, finish);
                QSortStruc(right);
            }
        }

Взглянем теперь на результаты численных экспериментов и посмотрим, что дает введение потоков в алгоритм быстрой сортировки:

Как видите, все три метода легко справляются с сортировкой достаточно больших массивов. Время сортировки практически сравнимо с величиной ошибки измерения времени. Введение потоков не дает никаких преимуществ. Классический последовательный алгоритм не уступает пальмы первенства. Это еще раз доказывает, что к введению параллелизма следует подходить с осторожностью, поскольку это не только приводит к усложнению программы, но может приводить и к замедлению ее работы.

< Лекция 4 || Лекция 5: 1234 || Лекция 6 >
Алексей Рыжков
Алексей Рыжков

не хватает одного параметра:

static void Main(string[] args)
        {
            x = new int[n];
            Print(Sample1,"original");
            Print(Sample1P, "paralel");
            Console.Read();
        }

Никита Белов
Никита Белов

Выставил оценки курса и заданий, начал писать замечания. После нажатия кнопки "Enter" окно отзыва пропало, открыть его снова не могу. Кнопка "Удалить комментарий" в разделе "Мнения" не работает. Как мне отредактировать недописанный отзыв?

Анатолий Кирсанов
Анатолий Кирсанов
Россия, Тамбов, Российский Новый Университет, 2012
Алексей Горячих
Алексей Горячих
Россия