Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
 Аватар для zewer
2357 / 1775 / 212
Регистрация: 07.01.2011
Сообщений: 10,342

Эффект от применения потоков к сумированию элементов массива

12.11.2015, 02:29. Показов 1763. Ответов 33
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здраствуйте, есть массив на 100000000 элементов. В него пихаем рандомные данные типа double.
Потом считаем суму всех элементов.
Получаеться, что выполнение в главном потоке в 3 раза быстрее, чем, если бы запускать 2 потока
Почему так?
И почему результаты не совпадают в дробной части?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
using System;
using System.Runtime;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TestLibrary;
using System.Collections;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
 
class Program
{
    public static double suma1 = 0;
    public static double suma2 = 0;
    public static double suma = 0;
 
    static void Main(string[] args)
    {
        double[] a = new double[100000000];//наш массив
        Random rnd = new Random();
        for(int i=0; i<a.Length;i++)
        {
            a[i] = rnd.NextDouble()*rnd.Next(1000);//пихаем рандом числа в массив
        }
 
        Console.WriteLine("/******1 THREAT******/");
        Stopwatch sw = new Stopwatch();
        sw.Start();
        Func(a);//выполняем в главном потоке
        sw.Stop();
        Console.WriteLine(sw.Elapsed);
 
        sw.Reset();
        
        Thread th1 = new Thread(() => Func1(a));//0-Длина/2
        Thread th2 = new Thread(() => Func2(a));//Длина/2 до Длины
        th1.Priority = ThreadPriority.Highest;
        th2.Priority = ThreadPriority.Highest;
        Console.WriteLine("/******MULTI THREAT******/");
        sw.Start();
        th1.Start();
        th2.Start();
        th1.Join();
        th2.Join();
        Console.WriteLine(suma1 + suma2);
        sw.Stop();
        Console.WriteLine(sw.Elapsed);
    }
 
    static void Func(double[] a)
    {
        for (int i=0; i<a.Length; i++)
        {
            suma += a[i];
        }
        Console.WriteLine(suma);
    }
 
    static void Func1(double[] a)
    {
        for (int i = 0; i < a.Length/2; i++)
        {
            suma1 += a[i];
        }
    }
    static void Func2(double[] a)
    {
        for (int i = a.Length/2; i < a.Length; i++)
        {
            suma2 += a[i];
        }
    }
}
Результат
/******1 THREAT******/
24975723278,0035
00:00:00.5711327
/******MULTI THREAT******/
24975723278,0043
00:00:01.4812455
Press any key to continue . . .
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.11.2015, 02:29
Ответы с готовыми решениями:

Ошибка из-за применения массива
Работаю с файлом *.xls через OpenOffice Calc. На форме 2 элемента RadioButton1 и RadioButton2. Если выбрать RadioButton1 дважды, то все...

Как обратиться к элементам массива БЕЗ применения индексов
Есть динамический массив А. Поменять местами максимальный элемент главной и побочной диагоналей с элементом, расположенным на пересечении...

Связка массива структур с классом без применения указателей
У меня такая задача по учебе: Написать программу с использованием объектно-ориентированных технологий. Количество созданных классов –...

33
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18298 / 14222 / 5368
Регистрация: 17.03.2014
Сообщений: 28,898
Записей в блоге: 1
12.11.2015, 03:47
Лучший ответ Сообщение было отмечено zewer как решение

Решение

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

Цитата Сообщение от zewer Посмотреть сообщение
И почему результаты не совпадают в дробной части?
Потому что double оперирует с некоторой погрешностью и из-за сложения в разном порядке эта погрешность набегает по разному.

Цитата Сообщение от zewer Посмотреть сообщение
1 THREAT
Threat переводится "угроза". Поток это Thread
1
-39 / 2 / 1
Регистрация: 21.09.2015
Сообщений: 58
12.11.2015, 09:36
Применяйте библиотеку BindingAndSeviceCoreParallel
Инструмент многопоточного программирования
и все станет на свои места, N потоков выполнят задание в N раз быстрее. Собственно для этого она и создавалась.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
12.11.2015, 10:38
Попробовал несколько вариантов суммирования. Массив того-же размера, метод заполнения тот-же. Результаты:
Creating time: 3608 ms
By FOR elapsed 514 ms, sum = 24977824773,1524
By FOREACH elapsed 503 ms, sum = 24977824773,1524
By LINQ elapsed 710 ms, sum = 24977824773,1524
By PLINQ elapsed 248 ms, sum = 24977824773,1551
By TASKS elapsed 2637 ms, sum = 24977824773,1574

Добавлено через 8 минут
Dedoc, много начитан об этой чудо-библиотеке, но ниразу не видел её в действии. Если несложно повторите эксперимент с сумированием вышепреведённого массива и выложите код на посмотреть.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18298 / 14222 / 5368
Регистрация: 17.03.2014
Сообщений: 28,898
Записей в блоге: 1
12.11.2015, 10:43
Цитата Сообщение от Dedoc Посмотреть сообщение
и все станет на свои места, N потоков выполнят задание в N раз быстрее.
Совсем необязательно. Это как минимум зависит от железа и задачи. На двухяжерном процессе созданияе 8 потоков даст ускорения в 8 раз.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
12.11.2015, 11:10
Ради интереса попробовал в двух вариантах (оба с применением PLINQ). Результат на скрине.
Миниатюры
Эффект от применения потоков к сумированию элементов массива  
1
-39 / 2 / 1
Регистрация: 21.09.2015
Сообщений: 58
12.11.2015, 11:25
Цитата Сообщение от aquaMakc Посмотреть сообщение
Если несложно повторите эксперимент с сумированием вышепреведённого массива и выложите код на посмотреть.
Суммирование слишком простая задача, секундой раньше, секундой позже – нет разницы.
Здесь https://sites.google.com/site/algonauts/Home/fajly
в файле Sorting_Demo.cs – пример сортировки массива. Можете сами поэкспериментировать, измените суммирование на сортировку пузырьком. При длине массива 10.000.000 мой чудо-богатырь FX 8320 пятью ядрами пыхтит часами. Это хорошая задача.
Суммировать не буду, но отдельно выполню сортировку в однопоточном режиме для сравнения.


Цитата Сообщение от OwenGlendower Посмотреть сообщение
На двухяжерном процессе созданияе 8 потоков даст ускорения в 8 раз.
Нет конечно, будет только хуже. Поток – логическое понятие, надо привязать его к железу, т.е. к ядрам процессора. Они реально толкают цепочки команд .
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
12.11.2015, 11:32
Цитата Сообщение от Dedoc Посмотреть сообщение
Суммировать не буду, но отдельно выполню сортировку в однопоточном режиме для сравнения.
Мне не интересна сортировка. Мне интересно сравнение эффективности вашей библиотеки со стандартными при решении данной задачи, а также затраты времени и объёмы кода. У меня на реализацию 5 разных способов ушло около получаса, включая создание нового проекта, консультирование коллег по телефону, просмотр других разделов форума и заваривание чая. Код ниже.

Ваш отказ в решении ДАННОЙ задачи я могу рассматривать, как невозможность реализации в приемлимых временных рамках.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
    class Program
    {
        static double[] arr = new double[100000000];
        static double sum = 0, sumPart1 = 0, sumPart2 = 0;
 
        delegate void sumDel(double[] arr);
 
        static void Main(string[] args)
        {
            Random rnd = new Random();
            Stopwatch sw = new Stopwatch();
            
            Task sumTask1, sumTask2;
            sw.Start();
            for (int i = 0; i < arr.Length; i++)
                arr[i] = rnd.NextDouble() * rnd.Next(1000);
            sw.Stop();
            Console.WriteLine("Creating time: {0} ms", sw.ElapsedMilliseconds);
            sw.Restart();
            for (int i = 0; i < arr.Length; i++)
                sum += arr[i];
            sw.Stop();
            Console.WriteLine("By FOR elapsed {0} ms, sum = {1}", sw.ElapsedMilliseconds, sum);
            sum = 0;
            sw.Restart();
            foreach (double d in arr)
                sum += d;
            sw.Stop();
            Console.WriteLine("By FOREACH elapsed {0} ms, sum = {1}", sw.ElapsedMilliseconds, sum);
            sum = 0;
            sw.Restart();
            sum = arr.Sum();
            sw.Stop();
            Console.WriteLine("By LINQ elapsed {0} ms, sum = {1}", sw.ElapsedMilliseconds, sum);
            sum = 0;
            sw.Restart();
            sum = arr.AsParallel().WithDegreeOfParallelism(Environment.ProcessorCount).Sum();
            sw.Stop();
            Console.WriteLine("By PLINQ elapsed {0} ms, sum = {1}", sw.ElapsedMilliseconds, sum);
            sum = 0;
            sw.Restart();
            sumTask1 = new Task(sum1);
            sumTask2 = new Task(sum2);
            sumTask1.Start();
            sumTask2.Start();
            Task.WaitAll(sumTask1, sumTask2);
            sum = sumPart1 + sumPart2;
            sw.Stop();
            Console.WriteLine("By TASKS elapsed {0} ms, sum = {1}", sw.ElapsedMilliseconds, sum);
            //Console.ReadKey();
        }
 
        static void sum1 ()
        {
            for (int i = 0; i < arr.Length / 2; i++)
            {
                sumPart1 += arr[i];
            }
        }
 
        static void sum2()
        {
            for (int i = arr.Length / 2; i < arr.Length; i++)
            {
                sumPart2 += arr[i];
            }
        }
    }
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
12.11.2015, 11:35
Цитата Сообщение от Dedoc Посмотреть сообщение
Суммирование слишком простая задача, секундой раньше, секундой позже – нет разницы.
Dedoc, ну как сказать...
Вот действительно, сделайте простой пример - суммирование большого массива. И проведите его всеми способами - обычный Thread, Task, PLINQ и с применением вашей библиотеки.
И выложите результат. Тогда сразу будет ясно, имеет она преимущества перед штатными средствами или нет.

Добавлено через 29 секунд
Цитата Сообщение от aquaMakc Посмотреть сообщение
Мне интересно сравнение эффективности вашей библиотеки со стандартными при решении данной задачи, а также затраты времени и объёмы кода.
100500 присоединяюсь)))
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18298 / 14222 / 5368
Регистрация: 17.03.2014
Сообщений: 28,898
Записей в блоге: 1
12.11.2015, 11:40
Цитата Сообщение от Dedoc Посмотреть сообщение
Цитата Сообщение от OwenGlendower Посмотреть сообщение
На двухяжерном процессе созданияе 8 потоков [не] даст ускорения в 8 раз.
Нет конечно, будет только хуже. Поток – логическое понятие, надо привязать его к железу, т.е. к ядрам процессора. Они реально толкают цепочки команд .
Угу. Я умудрился пропустить "не" в своем ответе.
0
-39 / 2 / 1
Регистрация: 21.09.2015
Сообщений: 58
12.11.2015, 12:13
Цитата Сообщение от aquaMakc Посмотреть сообщение
У меня на реализацию 5 разных способов ушло около получаса, включая создание нового проекта, консультирование коллег по телефону, просмотр других разделов форума и заваривание чая.
Уважаемый aquaMakc, такие рассуждения неверны. Работа с библиотекой требует навыка, без этого не обойтись, но в целом все достаточно тривиально. Стандартные средства не обеспечат реализацию всего потенциала многоядерных процессоров, а библиотека реализована так, что подключает все ядра полностью. Чем больше ядер процессора, тем преимущество над стандартными средствами будет выше. Сейчас разрабатываются процессоры с 16 и более ядрами. Представьте, что задача стандартными средствами будет считаться на 64-х ядерном процессоре сутки, а на библиотеке несколько минут. Сколько же телефонных звонков можно совершить за сэкономленное время, о чае просто умолчу?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
12.11.2015, 12:25
Цитата Сообщение от Dedoc Посмотреть сообщение
Стандартные средства не обеспечат реализацию всего потенциала многоядерных процессоров, а библиотека реализована так, что подключает все ядра полностью.
Я все понял. В Microsoft сидят идиоты и недоумки, и ничего не могут сделать толковое.
Цитата Сообщение от Dedoc Посмотреть сообщение
задача стандартными средствами будет считаться на 64-х ядерном процессоре сутки, а на библиотеке несколько минут
Пример, приведите простой и наглядный пример (вопрос выше, это просто и наглядно). Без этого все слова - колебания воздуха и ничего не стОят.
0
-39 / 2 / 1
Регистрация: 21.09.2015
Сообщений: 58
12.11.2015, 12:38
Цитата Сообщение от insite2012 Посмотреть сообщение
Я все понял. В Microsoft сидят идиоты и недоумки, и ничего не могут сделать толковое
Это не так, MS – глубокоуважаемая и очень весомая фирма с огромным творческим потенциалом и гигантскими наработками к сегодняшнему дню. Видимо такая задача перед ними не стояла, иначе они решили бы ее легко.


Цитата Сообщение от insite2012 Посмотреть сообщение
Пример, приведите простой и наглядный
Пример сравнения с однопотоковым режимом приведу, писал об этом.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
12.11.2015, 13:04
Цитата Сообщение от Dedoc Посмотреть сообщение
Пример сравнения с однопотоковым режимом приведу, писал об этом.
вот задача в топике. Её надо решить в нескольких потоках так, чтобы это было быстрее, чем в одном потоке.
При разбиении задачи на 2 потока Thread этого добиться не получилось. Вот он звёздный час твоей библиотеки. Докажи, что всё о чём ты уже несколько месяцев говоришь является правдой. Реши эту задачу. Разбей на потоки, уменьши время выполнения.
0
 Аватар для zewer
2357 / 1775 / 212
Регистрация: 07.01.2011
Сообщений: 10,342
12.11.2015, 17:32  [ТС]
спасибо всем отвечающим.
Такой вопрос, видел применение обычных потоков(Thread), библиотеки с тасками(Tasks), может еще есть другие, PLINQ(от модератора выше, но сам не знаком с этим).
Какая из этих технологий дает больше всего прироста, и с какой лучше всего начать знакомиться?
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
12.11.2015, 17:36
Цитата Сообщение от zewer Посмотреть сообщение
Какая из этих технологий дает больше всего прироста, и с какой лучше всего начать знакомиться?
Сравнение производительности нескольких вариантов я уже приводил в начале поста. А знакомиться предлагаю в следующей последовательности:
Thread -> Task -> BackGroundWorker
и параллельно LINQ->PLINQ->PARTITIONER
0
 Аватар для zewer
2357 / 1775 / 212
Регистрация: 07.01.2011
Сообщений: 10,342
12.11.2015, 17:47  [ТС]
Цитата Сообщение от aquaMakc Посмотреть сообщение
Сравнение производительности нескольких вариантов
выходит что PLINQ самый производительный, причем раз в 7 быстрее обычных Threads ?
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
12.11.2015, 18:06
Лучший ответ Сообщение было отмечено zewer как решение

Решение

Цитата Сообщение от zewer Посмотреть сообщение
выходит что PLINQ самый производительный, причем раз в 7 быстрее обычных Threads ?
Для конкретно этой задачи да, но во-первых, и у тебя и у меня шло разделение по 2-м потокам, а при выполнении PLINQ я указывал использовать все процессоры (ядра), коих у меня 4:

C#
1
sum = arr.AsParallel().WithDegreeOfParallelism(Environment.ProcessorCount).Sum();
Во-вторых, использование отдельных потоков для таких тривиальных задач, как суммирование - не выгодно. Они используются для других вещей, например, вынос задачи в поток, независимый от интерфейса. Конкретно у меня - это обмен данными с оборудованием по различным каналам связи в том числе с большой задержкой ожидания ответа. Еслиб я эту задачу выполнял в основном потоке, то до получения ответа вешался бы интерфейс пользователя.
1
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18298 / 14222 / 5368
Регистрация: 17.03.2014
Сообщений: 28,898
Записей в блоге: 1
12.11.2015, 19:51
Цитата Сообщение от insite2012 Посмотреть сообщение
Пример, приведите простой и наглядный пример (вопрос выше, это просто и наглядно). Без этого все слова - колебания воздуха и ничего не стОят.
Присоединяюсь.
0
 Аватар для zewer
2357 / 1775 / 212
Регистрация: 07.01.2011
Сообщений: 10,342
12.11.2015, 20:09  [ТС]
всем спасибо за ответы.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
12.11.2015, 20:09
Помогаю со студенческими работами здесь

Последнее значение массива x, после применения функции обращается в 0
#include &lt;stdio.h&gt; #include &lt;math.h&gt; double fun1(const double x); double fun2(const double x); void transform(const double...

Как реализовать код без применения ассоциативного массива (map)?
Имеется такой код. Как можно его изменить, не использую массив map? #include &lt;iostream&gt; #include &lt;map&gt; #include &lt;string&gt; ...

Как правильно вывести строку двухмерного массива без применения цикла
Подскажите пожалуйста, вот я обьявляю строку char s; Если Мне нужен массив строк, то я обьявляю его s Как дальше использоваь второй...

Как сделать эффект размытия (эффект стекла) в Xaml?
Как сделать эффект размытия(эффект стекла) в Xaml?

Необходимо разработать функцию, вычисляющую среднее арифметическое массива (без применения рекурсии)
Не получается написать программку.&quot;Символ используется для хранения индексированных данных (аналогично массиву). Свойство Length содержит...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru