|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
|||||||||||
Многопоточное программирование: как распараллелить цикл?12.05.2019, 19:06. Показов 10442. Ответов 45
Здравствуйте, господа. Возможно, я сейчас спрошу глупость, но тем не менее. В интернетах найти ответа не смог.
Допустим, у меня есть цикл do-while, в котором у меня выполняются операции - функции - с большуууууущим вектором, таких функций несколько, причем эти функции принципиально последовательны, результат работы предыдущей функции влияет на выполнение последующей. Но в пределах одной функции, которая работает с вектором поэлементно вполне возможно реализовать параллельные вычисления для ускорения процесса. Вопрос! А как это сделать правильно? В каждой функции есть range-based цикл, который перебирает элементы вектора. Мне пришел в голову (тупой) вариант - просто распилить вектор, допустим, на 4 части и работать с каждой из частей, получилось примерно следующее:
Но я могу засунуть выполнение, допустим, f1(V_1..4) в разные потоки и выполнять это дело параллельно. Мой очень фиговый вариант:
потоков, и в результате вместо выигрыша в скорости от параллельных вычислений я получаю проигрыш в этой самой скорости по сравнению даже со случаем тупого последовательного счета. Я бы хотел (хотел бы я, ага...), чтобы у меня где-то в мэйне открывалось три потока, в которые я бы по мере необходимости закидывал выполнение нужных функций. Но с библиотекой thread такого добиться не получается. Находил в интернетах информацию, что можно использовать библиотеку pthread.h, но я так понял, что она типа устаревшая, я ее в моей VS-2017 даже подключить не могу. Как быть? Заранее благодарю за уделенное внимание)
0
|
|||||||||||
| 12.05.2019, 19:06 | |
|
Ответы с готовыми решениями:
45
Как распараллелить цикл while? Распараллелить цикл Многопоточное программирование |
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
|
| 13.05.2019, 22:06 | |
|
0
|
|
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
|
| 13.05.2019, 22:29 [ТС] | |
|
0
|
|
|
79 / 60 / 19
Регистрация: 22.11.2015
Сообщений: 193
|
||
| 14.05.2019, 04:42 | ||
|
Для флагов (в Вашем случаи) лучше использовать std::atomic_flag либо std::atomic<bool> либо std::atomic<int> http://www.cplusplus.com/refer... omic_flag/
0
|
||
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
||
| 14.05.2019, 10:55 [ТС] | ||
|
0
|
||
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
||||||
| 21.05.2019, 13:40 [ТС] | ||||||
|
Господа, не знаю, есть ли кто живой в этой теме.
В первую очередь, большое спасибо всем за помощь и действительно дельные советы. Написал я очередной вариант моего многопоточного расчета с учетом всех замечаний, сейчас это все выглядит следующим образом:
нужного флага, после чего считает (вызывает мою функцию), отправляет сигнал, что она посчитала, ставит флаг СТОП, а затем снова ждет. В мэйне в цикле я в нужный момент времени выставляю флаги, а затем пинаю условные переменные (она у каждого экземпляра класса Els, который и содержит метод Calc_processing, своя, как и мьютекс, значит у каждого потока своя пара переменная-мьютекс). После этого я в мэйне тоже запускаю вычисления с оставшимся вектором типа MyClass (специально создаю вектор векторов размером с число потоков, а потоков открываю на один меньше - один из векторов будет обрабатываться в основном потоке). После того, как в мэйне все посчиталось, опрашиваю каждый поток на предмет окончания вычислений с помощью wait (там уже задействована другая пара условная переменная - мьютекс) + флаг STOP. После все повторяется с другой функцией. Я вижу работу моего кода так. Правда, Студия видит это по-другому. Почему-то в какие-то моменты времени прога виснет или ругается на out-of-range вектора. Все перепроверил, вектора по длинам вроде бы все согласованы. Зависает прога, судя по всему, во время ожидания в теле функции Calc_Processing, при этом мне удалось поймать ошибку, как на скриншоте. Господа, с чем это может быть связано? Какие мысли? Благодарю за уделенное внимание)
0
|
||||||
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
||
| 21.05.2019, 13:48 [ТС] | ||
|
(подробности - выше)
0
|
||
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
|||||||
| 21.05.2019, 15:08 | |||||||
В Thread_function::Сalc_processing то же самое Добавлено через 2 минуты У тебя должен быть один мьютекс и одна condition_variable, общие для всех потоков, посмотри мой код
1
|
|||||||
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
|||
| 21.05.2019, 16:53 [ТС] | |||
|
Добавлено через 2 минуты к срабатыванию функции wait() в ожидающем потоке?
0
|
|||
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
|||
| 21.05.2019, 17:24 | |||
|
Добавлено через 18 минут Добавлено через 3 минуты В моём случае, он проверит есть ли ещё необработанные данные, если есть - обработает. Т.е. блоков массива (или массивов) может быть сколько угодно, я гарантирую, что все они будут обработаны Добавлено через 2 минуты В твоём случае - ты последовательно запускаешь все потоки. Соответственно может получится, что первый уже всё сделал и не знает чем заняться, а последний ещё даже не запустился.
0
|
|||
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
||||
| 21.05.2019, 17:33 [ТС] | ||||
|
Работает! Спасибо огромное за совет! Осталось только добиться одновременного запуска потоков Добавлено через 2 минуты Ну или я глупенький..
0
|
||||
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
||
| 21.05.2019, 17:48 | ||
|
Под блокировкой ждут события, что появились данные для обработки - if (m_i < m_data.size()) или останока - stop == true Вычисляют какой блок им обрабатывать i = m_i; n = m_i = std::min(m_data.size(), m_i + m_block_size); Выставляют признак что заняты - ++m_inuse; Снимают блокировку Обрабатывают данные Под блокировкой снимают признак, что заняты --m_inuse; Добавлено через 5 минут Поток main() в цикле: Под блокировкой заполняет массив Выставляет признак, что есть данные data.m_i = 0; Сообщает потоком, что можно работать data.m_cv.notify_all(); Снимает блокировку Ждёт, пока нет больше данных для обработки data.m_i < data.m_data.size() и все потоки завершили обработку данных data.m_inuse != 0 После выхода из цикла: под блокировкой выставляет data.m_stop = true; и сообщает об этом потокам Снимает блокировку и ждёт пока потоки завершатся thread.join();
1
|
||
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
|||||||||||
| 23.05.2019, 14:34 [ТС] | |||||||||||
|
oleg-m1973, я вроде разобрался, спасибо огромное за помощь. Во многом воспользовался
Вашим кодом, но немного переделал его "под себя". Все шуршит, все работает, НО... Опять возникла проблемка) Сейчас мой код выглядит так:
элемент - это ячейка сетки.Структура этого класса не так важна. Допустим, в нем есть нестатическое поле int Value, которое хранит число обращений к данной ячейке сетки со стороны векторов MyVect.MyVectors_1...procs, причем КАЖДЫЙ ЭЛЕМЕНТ ВЕКТОРА МОЖЕТ ОБРАТИТЬСЯ К СЕТКЕ НЕ БОЛЕЕ И НЕ МЕНЕЕ ОДНОГО РАЗА, таким образом полное число обращений к сетке (то есть ко всем элементам массива mesh[Size], если просуммировать их поля Value) должно в точности совпадать с СУММАРНЫМ числом элементов во ВСЕХ векторах MyVect.MyVectors_1...procs. Переменная Contr_Sum также отслеживает число "учтенных", "задействованных" элементов векторов MyVect.MyVectors_1...procs. По моей логике, сумма полей Value массива mesh[Size] должна совпадать с контрольной суммой Contr_Sum и с полным числом всех элементов всех векторов. Но у меня все эти три числа РАЗНЫЕ! Количество элементов в векторах самое большое, сумма сумма значений полей Value массива mesh[Size] поменьше (иногда существенно, иногда не очень), а Contr_Sum сильно меньше. Таким образом, я делаю вывод, что мои функции f1 и f2 обрабатывают не все элементы векторов. Как бы не так! Сами функции выглядят примерно так:
не выявлено: всегда четко (Count == V_1..procs.size()) - true. Но по завершению расчетов всеми потоками оказывается, что Contr_Sum сильно отличается от Суммы размеров всех векторов V_1..procs, как и сумма всех полей Value сетки mesh. Причем и между собой сумма (mesh[i].value) и Contr_Sum не равны! Значит, я не могу утверждать, что после отработки всех потоков у меня запишутся ВСЕ необходимые данные. ХОТЯ! в пределах КАЖДОГО потока счетчик итераций Count неизменно совпадает с размерами передаваемого вектора. Тогда почему так криво инкрементируются внешние счетчики??? Блокировка стоит, одновременно потоки попытаться испоганить данные не могут. Добавлено через 40 минут oleg-m1973, в остальном - все отлично работает) спасибо за помощь)
0
|
|||||||||||
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
|||
| 23.05.2019, 15:18 | |||
|
Добавлено через 33 секунды
0
|
|||
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
|||
| 23.05.2019, 15:21 [ТС] | |||
|
0
|
|||
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
|
| 23.05.2019, 15:23 | |
|
0
|
|
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
||
| 23.05.2019, 15:25 [ТС] | ||
|
Что плохо
0
|
||
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
|
| 23.05.2019, 15:25 | |
|
У тебя разные потоки обращаются к одно ячейке mesh?
0
|
|
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
|||
| 23.05.2019, 15:27 [ТС] | |||
|
Пока что я убедился, скорее, в обратном) Добавлено через 1 минуту
0
|
|||
|
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
|
|
| 23.05.2019, 15:28 | |
|
0
|
|
|
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
|
|||||||||
| 23.05.2019, 15:34 [ТС] | |||||||||
|
Добавлено через 4 минуты
0
|
|||||||||
| 23.05.2019, 15:34 | |
|
многопоточное программирование на с++ Многопоточное программирование Многопоточное программирование Многопоточное программирование Не получается распараллелить цикл Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла:
Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
|
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет
Новости компьютерного мира и их обсуждение (4)
Салют, шампанское, овации!
:drink:
|
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр.
Дословно, отклонённая. . .
|
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы
Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
|
|
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
|
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2.
Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
|
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
|
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
|