Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Parallel Programming ( Не разберусь не как )


Автор: 56illusion 7.9.2010, 01:01
Всем привет.
Я тут ночью заседелся и решил вникнуть в паралельное программирование, так как оно значительно сокращает время и увеличивает скорость программы.
А так же Я решил провести  маленький эксперимент и проверить на сколько сокращаеться время действия программы.
написал я не сложный алгоритм для отображение всех вариантов слов состоящих из 4 букав.

Код без паралелизма
-----------------------------------

Код


class Program
    {
        static void PasswordSearth()
        {
            char[] pass = new char[4];
            int count = 0;
            for (int a = 65; a <= 90; a++)
            {
                pass[0] = (char)a;
                for (int b = 65; b <= 90; b++)
                {
                    pass[1] = (char)b;

                    for (int c = 65; c <= 90; c++)
                    {
                        pass[2] = (char)c;

                        for (int d = 65; d <= 90; d++)
                        {
                            pass[3] = (char)d;

                            for (int i = 0; i < pass.Length; i++)
                            {
                                Console.Write(pass[i]);
                            }
                            Console.WriteLine("");
                            count++;
                        }

                    }

                }
            }
 static void Main(string[] args)
        {
            DateTime Before = DateTime.Now;
            PasswordSearth();
            DateTime After = DateTime.Now;
            TimeSpan Interval = After - Before;
            Console.WriteLine("Minuts:" + Interval.Minutes);
            Console.WriteLine("Seconds:" + Interval.Seconds);
            Console.WriteLine("Total proccesing time: {0},{1}", Interval.Minutes, Interval.Seconds);

        }
    }




и тот же смысл только с паралелизмом
---------------------------------------------------
Код

class Program
    {
        static void PasswordSearth()
        {
            char[] pass = new char[4];
            int count = 0;
          
              Parallel.For(65, 90, a => 
            { 
                pass[0] = (char)a;
                Parallel.For(65, 90, b =>
                    {
                        pass[1] = (char)b;
                        Parallel.For(65, 90, c =>
                            {
                                pass[2] = (char)c;
                                Parallel.For(65, 90, d =>
                                    {
                                        pass[3] = (char)d;

                                        Parallel.For(0, pass.Length, i =>
                                            {
                                                Console.Write(pass[i]);
                                            });
                                        Console.WriteLine("");
                                        count++;

                                    });
                            });
                    });
            
            });

        }
 static void Main(string[] args)
        {
            DateTime Before = DateTime.Now;
            PasswordSearth();
            DateTime After = DateTime.Now;
            TimeSpan Interval = After - Before;
            Console.WriteLine("Minuts:" + Interval.Minutes);
            Console.WriteLine("Seconds:" + Interval.Seconds);
            Console.WriteLine("Total proccesing time: {0},{1}", Interval.Minutes, Interval.Seconds);

        }
    }



При компиляций каждой из программ я наблюдал за состояние процессора. В случаи паралелизма процессор работал на максимум но вот время исполнение в двое больше!!!!!!!!!!!
Но я вить ожидал что время в 2 раза будет ниже... как такое возможно???

кстате в программе с паралелизмом отображаються и слова с большим количеством букв чем 4...и ето тоже невозможно, вить массив у меня только на 4..
Вобщем я запутолся.
-----------------------------------------------

Если комуто интересна эта тема помогите разобраться в чём дело... может быть я не правельно  написал код с параллелизмом???

Автор: 6atoh 7.9.2010, 11:14
Взглянув на ваш код с параллелизацией, могу сказать следующее:
1. Параллелизация внутри параллелизации - это очень плохо. В вашем алгоритме можно наблюдать 4(!) вложенных цикла с параллелизацией. Перепишите алгоритм так, чтобы он использовал лишь один цикл, либо цепочку циклов.
2. При параллелизации необходимо заботиться о синхронизации данных между потоками. В данном случае локальный массив pass, содержимое которого выводится на консоль, не защищен никоим образом от одновременного доступа к нему разных потоков. Соответственно, от алгоритма не стоит ожидать корректной работы.

Учтите, что без использования параллелизации ваш код выполняется последовательно (1 путь исполнения). При использовании параллелизации он выполняется параллельно (2 пути исполнения, нужна синхронизация), а наличие вложенных циклов многократно увеличивает кол-во возможных путей исполнения и работу алгоритма предсказать сложно. Вывод: ваш алгоритм не подходит для применения параллелизации.

Автор: 6atoh 7.9.2010, 12:56
http://www.albahari.com/threading/part5.aspx#_The_Parallel_Classочень хорошо написано про использование класса Parallel, в том числе и метода For.

Цитата

Parallel.For and Parallel.ForEach usually work best on outer rather than inner loops. This is because with the former, you’re offering larger chunks of work to parallelize, diluting the management overhead. Parallelizing both inner and outer loops is usually unnecessary.


Таким образом, я бы сделал следующее с вашим алгоритмом:
1. Заменил все вложенные Parallel.For на обычные for-выражения.
2. Сделал бы вывод на консоль массива одной операцией WriteLine, а не последовательностью вызовов Write.

Код

char[] pass = new char[4];
int count = 0;

Parallel.For(65, 90, a =>
{
    pass[0] = (char)a;
    for (int b = 65; b <= 90; b++)
    {
        pass[1] = (char)b;
        for (int c = 65; c <= 90; c++)
        {
            pass[2] = (char)c;
            for (int d = 65; d <= 90; d++)
            {
                pass[3] = (char)d;
                Console.WriteLine(pass);
                count++;
            }
        }
    }
});

Автор: gambit 7.9.2010, 13:19
Цитата(56illusion @  7.9.2010,  01:01 Найти цитируемый пост)
2 раза будет ниже

это зависит от кучи параметров, но конкретно на 2 ядрах, при самых лучших условиях, в  2 раза быть не может, ибо тратиться время на создание потоков и их синхронизацию, и на 2 ядрах средний прирост составляет 1,6

Цитата(56illusion @  7.9.2010,  01:01 Найти цитируемый пост)
я не сложный алгоритм

в этом суть, у вас ресурсы затраченные на создание потоков превышаю, полезный коэффициент. Если бы распараллелили, например, поворот картинок в папке, то разницу увидели.

Код

Parallel.For(65, 90, b =>
                    {
                        pass[1] = (char)b;
                        Parallel.For(65, 90, c =>
                            {
                                pass[2] = (char)c;
                                Parallel.For(65, 90, d =>
и т.д.

убиться....
Parallel.For сам решает сколько потоков для какой задачи создать, и как их распределить по ядрам, а вы принуждаете его создавать и создавать их.

в любом случае посмотрите, для начала, более классические подходы к потокам, например backgroundWorker

Автор: 56illusion 7.9.2010, 14:28
6atoh Большое спасибо вам. Вы мне очень помогли и прекрасно пояснили в чём заключалась моя ошибка.
По интернету встретил множество информаций про параллелизм но не увидел не одной статьй про то как правельно применять его.
Скажите а в процессе самого параллелизма как возможно то что код сам увеличивает длину массива??? на консоле были видны слова и по 8 букв..
Возможно ли что два слова отображались паралельно и одновременно???

gambit раскажите мне пожалуйсто про backgroundWorker
в гугле искать?

Спасибо всем

Автор: CYBERDREAM 7.9.2010, 14:30
http://msdn.microsoft.com/ru-ru/library/8xs8549b.aspx

Автор: 56illusion 7.9.2010, 14:40
Я скомпилировал код который показал мне 6atoh. время программы 4.7 минуты. А время программы без параллелизма 2.7 минуты. Почему же время только возрастает???

Автор: 6atoh 7.9.2010, 15:08
Цитата(56illusion @  7.9.2010,  13:28 Найти цитируемый пост)
Скажите а в процессе самого параллелизма как возможно то что код сам увеличивает длину массива??? на консоле были видны слова и по 8 букв..
Возможно ли что два слова отображались паралельно и одновременно???

Это происходит потому, что у вас используется Console.Write. В данном случае output консоли - это общий ресурс, запись в который необходимо как-то упорядочить, чтобы строки выводились по 4 символа. Я предложил это сделать, заменив Console.Write(pass[i]) на Console.WriteLine(pass);

Цитата(56illusion @  7.9.2010,  13:40 Найти цитируемый пост)
Я скомпилировал код который показал мне 6atoh. время программы 4.7 минуты. А время программы без параллелизма 2.7 минуты. Почему же время только возрастает??? 

Во-первых для таких измерений я бы рекомендовал использовать http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx, вместо DateTime.Now. Это на будущее.
Во-вторых, как уже сказал gambit, в данном случае затраты на создание потоков и их синхронизацию могут превышать затраты на выполнение самого алгоритма.
На моей машине (Core2 Duo E8400 3.0GHz, 4Gb RAM) результаты следующие:
без параллелизации: 41 сек, загрузка ЦП ~ 45%
с параллелизацией:   45 сек, загрузка ЦП 100%

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

Автор: 56illusion 7.9.2010, 15:30
6atoh Спасибо вам. теперь Я всё ясно понял.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)