С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/6: Рейтинг темы: голосов - 6, средняя оценка - 4.50
1 / 1 / 1
Регистрация: 04.04.2014
Сообщений: 14

Определение четности чисел в большом объеме данных, используя 10 потоков

04.04.2014, 06:52. Показов 1223. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Как такое можно решить? Мозги кипят, вижу что при помощи Мютекса, но как? есть список типа int размером допустим 1000000 из произвольных чисел. При нажатии на кнопку ты должен запустить 10 потоков и дождаться их завершения. Каждый из потоков должен забрать себе одно число из списка и проверить четное оно или нет. если четное, увеличить общий счетчик. В итоге мы просто посчитаем количество четных чисел в списке с помощью нескольких потоков. используя Task и BlockingCollection. Помогите пожалуйста
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
04.04.2014, 06:52
Ответы с готовыми решениями:

Быстрый поиск в большом объеме данных
Добрый день. Есть файл в формата .txt (~4гб), в нем хранятся записи в строку, 1 запись = 1 строка. Каждая строка уникальна, повторов нету....

Копирования данных (в большом объеме) по определенным условиям
Здравствуйте люди добрые, у меня проблемы встроенные функции excel 2016 не позволяют нужный редизайн таблиц в ексель и сбор корректно...

Как правильнее работать с базой при большом объеме данных?
Вопрос в следующем. Есть база со множеством таблиц. И есть программа, которая одновременно работает с несколькими таблицами. А также...

11
192 / 199 / 82
Регистрация: 11.04.2013
Сообщений: 1,086
04.04.2014, 07:54
Цитата Сообщение от Richi9 Посмотреть сообщение
Каждый из потоков должен забрать себе одно число из списка и проверить четное оно или нет. если четное, увеличить общий счетчик.
Правильнее будет если каждый из потоков заберет себе диапазон чисел а именно 1000000 /10 т.е.

1 поток проверяет 0-100000
2 поток проверяет 100000-200000
......
далее поток находит четное число блокируем общий счетчик и инкрементируем его

C#
1
2
3
4
Lock(count)
{
count++;
}
хотя для операции инкремента есть более удобный метод щас не вспомню

что бы не использовать блокировок можно для каждого потока сделать отдельный счетчик , а потом просуммировать их по завершению
1
1057 / 864 / 195
Регистрация: 31.03.2010
Сообщений: 2,521
04.04.2014, 11:08
Цитата Сообщение от EVG-1980 Посмотреть сообщение
что бы не использовать блокировок можно для каждого потока сделать отдельный счетчик , а потом просуммировать их по завершению
только так и надо, а то теряется смысл в потоках

Добавлено через 1 минуту
хотя в условии задачи четко сказано реализовать общий счетчик - это пример на решения проблемы общего ресурса потоков, а не рабочий пример
1
1 / 1 / 1
Регистрация: 04.04.2014
Сообщений: 14
04.04.2014, 11:26  [ТС]
Так а как это все вооплотить? мозги уже кипят
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
04.04.2014, 14:11
Лучший ответ Сообщение было отмечено Richi9 как решение

Решение

Цитата Сообщение от Richi9 Посмотреть сообщение
используя Task и BlockingCollection.
Так это же вообще просто.

На примере консольного приложения:
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
class Program
{
    static int[] arr = new int[100000];
    static int counter = 0;
 
    static void Main()
    {
        var r = new Random();
        for (int i = 0; i < arr.Length; i++)
            arr[i] = r.Next();
 
        var queue = new BlockingCollection<int>(new ConcurrentQueue<int>(arr));
        queue.CompleteAdding();
 
        var tasks = new Task[10];
        for (int i = 0; i < tasks.Length; i++)
            tasks[i] = Task.Factory.StartNew(ProcessQueue, queue);
        Task.WaitAll(tasks);
        Console.WriteLine(counter);
    }
 
    static void ProcessQueue(object arg)
    {
        var queue = arg as BlockingCollection<int>;
        foreach (var value in queue.GetConsumingEnumerable())
            if (value % 2 == 0)
                Interlocked.Increment(ref counter);
    }
}
Под формы с кнопками уже сами переделаете.
1
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
04.04.2014, 14:35
kolorotur,
C#
1
2
3
4
5
6
7
8
9
static void ProcessQueue(object arg)
    {
        int counterPart = 0;
        var queue = arg as BlockingCollection<int>;
        foreach (var value in queue.GetConsumingEnumerable())
            if (value % 2 == 0)
                counterPart++;
        Interlocked.Add(ref counter, counterPart);
    }
2
52 / 45 / 4
Регистрация: 07.10.2010
Сообщений: 95
04.04.2014, 16:34
Не думаю, что на такой задаче использоваие синхронизации оправданно. Скорее всего 90% времни было потраченно на нее.

Мы не изменяем массив? Нет. Следовательно его можно использовать во всех тасках.
Можем ли мы выделить незавиисящий от других участок работы? Да. Мы можем масив разбить на куски и считать кол-во чисел в этом куске.

Если бы пользоваться всякими Parellel было нельзя, то я наверно сделал бы так:
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
 class Program
    {
        private static readonly int[] arr = new int[100000];
        static int counter = 0;
        private const int AmountOfTasks = 10;
 
        static void Main()
        {
            var r = new Random();
            for (int i = 0; i < arr.Length; i++)
                arr[i] = r.Next();
 
            var tasks = new Task<int>[AmountOfTasks];
            
            for (int i = 0; i < tasks.Length; i++)
            {
                int _i = i;
                tasks[i] = Task<int>.Factory.StartNew(ProcessQueue, _i);
            }
 
            Task.WaitAll(tasks);
 
            foreach (Task<int> task in tasks)
            {
                counter = task.Result;
            }
 
            Console.WriteLine(counter);
        }
 
 
        static int ProcessQueue(object arg)
        {
            int chankNumber = arg is int ? (int) arg : 0;
            int chank = arr.Length/AmountOfTasks + 1;
            int _counter = 0;
            for (int i = chankNumber * chank; i < chank * (chankNumber + 1) && i < arr.Length; i++)
            {
                int value = arr[i];
                if (value%2 == 0)
                {
                    _counter++;
                }
            }
            return _counter;
        }
    }
1
1 / 1 / 1
Регистрация: 04.04.2014
Сообщений: 14
04.04.2014, 17:14  [ТС]
Всем огромное спасибо
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
04.04.2014, 20:23
serefa, в моем варианте синхронизация происходит только 1 раз для каждого потока.

У вас же что-то странное. После цикла там будет просто лежать последнее значение. Да и сделали вы примерно то же, что и мы выше, только чуть дольше - сначала будет дожидатся выполнение всех потоков, а они могли бы тем временем уже частично сумму сложить.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
04.04.2014, 22:51
Psilon, ну да, так оно экономичнее
0
52 / 45 / 4
Регистрация: 07.10.2010
Сообщений: 95
05.04.2014, 21:14
Быстро печатал. Вместо =+ написал =.

Дальше:

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
75
76
77
78
79
80
81
82
class Program
    {
        static int[] arr = new int[100000000];
        static int counter = 0;
       private const int AmountOfTasks = 10;
        static void Main()
        {
            var r = new Random();
            for (int i = 0; i < arr.Length; i++)
                arr[i] = r.Next();
 
            Stopwatch stopWatch1 = Stopwatch.StartNew();
            Slution1();
            stopWatch1.Stop();
            Stopwatch stopWatch2 = Stopwatch.StartNew();
            Slution2();
            stopWatch2.Stop();
 
            Console.WriteLine("Slution1 - {0} Milliseconds \n Slution2 - {1} Milliseconds \n", stopWatch1.ElapsedMilliseconds, stopWatch2.ElapsedMilliseconds);
            Console.ReadKey();
        }
 
        private static void Slution2()
        {
            counter = 0;
            var tasks = new Task<int>[AmountOfTasks];
 
            for (int i = 0; i < tasks.Length; i++)
            {
                int _i = i;
                tasks[i] = Task<int>.Factory.StartNew(ProcessQueue2, _i);
            }
 
            Task.WaitAll(tasks);
 
            foreach (Task<int> task in tasks)
            {
                counter += task.Result;
            }
 
            Console.WriteLine(counter);
        }
 
        private static void Slution1()
        {
            counter = 0;
            var queue = new BlockingCollection<int>(new ConcurrentQueue<int>(arr));
            queue.CompleteAdding();
 
            var tasks = new Task[AmountOfTasks];
            for (int i = 0; i < tasks.Length; i++)
                tasks[i] = Task.Factory.StartNew(ProcessQueue, queue);
            Task.WaitAll(tasks);
            Console.WriteLine(counter);
        }
 
        static void ProcessQueue(object arg)
        {
            int counterPart = 0;
            var queue = arg as BlockingCollection<int>;
            foreach (var value in queue.GetConsumingEnumerable())
                if (value % 2 == 0)
                    counterPart++;
            Interlocked.Add(ref counter, counterPart);
        }
 
        static int ProcessQueue2(object arg)
        {
            int chankNumber = arg is int ? (int)arg : 0;
            int chank = arr.Length / AmountOfTasks + 1;
            int _counter = 0;
            for (int i = chankNumber * chank; i < chank * (chankNumber + 1) && i < arr.Length; i++)
            {
                int value = arr[i];
                if (value % 2 == 0)
                {
                    _counter++;
                }
            }
            return _counter;
        }
    }
И результат
49993550
49993550
Slution1 - 15749 Milliseconds
Slution2 - 278 Milliseconds

В вашем решении самая стремная часть - это BlockingCollection. На сколько я помню - по умолчанию это ConcurrentQueue. А там 100% синхронизация, когда достается элемент. Это раз.
И два - нафига она тут нужна? Массив не меняется. Из него ни чего не удаляется и не добавляется. Неизменяемые данные можно шарить между потоками.

Добавлено через 21 минуту
Psilon Даже последовательное выполнение быстрее твоего параллельного
16185 - твое
1165 - тупой прогон форыча.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
05.04.2014, 21:49
serefa, не мое, я просто показал что интерлокед в цикле не нужен.

Что касается твоего кода, то очевидно, что на тасках без синхронизации будет намного быстрее

Хотя полученный эффект в замедлении известен, нужно просто настраивать нормально многопоточность) но медленнее тасков будет все равно, факт.

Добавлено через 1 минуту
В вашем решении самая стремная часть - это BlockingCollection. На сколько я помню - по умолчанию это ConcurrentQueue. А там 100% синхронизация, когда достается элемент. Это раз.
И два - нафига она тут нужна? Массив не меняется. Из него ни чего не удаляется и не добавляется. Неизменяемые данные можно шарить между потоками.
Все верно, еще раз: я просто указал на место в конкретной реализации, не предлагая свою)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
05.04.2014, 21:49
Помогаю со студенческими работами здесь

Ошибка "Сервер не предоставил значащий ответ" при большом объеме данных
В общем клиент получает ошибку &quot;Сервер не предоставил значащий ответ&quot;, когда длина передаваемого массива объектов превышает 1103. На...

Определение четности/нечетности чисел
Программа узнавания четных и нечетных чисел

Определение четности и замена чисел
Входной файл (input.txt) содержит последовательность целых чисел в диапазоне от -2^31 до 2^31-1 включительно. Замените все чѐтные...

memo статус бар тормозит при большом объёме
Привет всем =) сталкнулся вот таким проблемой, статус бар тормозит при большом объёме... Как правильно добавить код чтобы статус бар не...

Оптимизация кода скрипта при большом объеме информации
Уважаемые друзья, нужна ваша помощь в оптимизации запроса, т.к. сервер не дает завершить выполнение скрипта, отдавая ошибку 504. Смысл...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru