Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.85/48: Рейтинг темы: голосов - 48, средняя оценка - 4.85
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80

Многопоточное программирование: как распараллелить цикл?

12.05.2019, 19:06. Показов 10067. Ответов 45

Студворк — интернет-сервис помощи студентам
Здравствуйте, господа. Возможно, я сейчас спрошу глупость, но тем не менее. В интернетах найти ответа не смог.

Допустим, у меня есть цикл do-while, в котором у меня выполняются операции - функции - с большуууууущим вектором,
таких функций несколько, причем эти функции принципиально последовательны, результат работы предыдущей функции
влияет на выполнение последующей. Но в пределах одной функции, которая работает с вектором поэлементно вполне
возможно реализовать параллельные вычисления для ускорения процесса. Вопрос! А как это сделать правильно?
В каждой функции есть range-based цикл, который перебирает элементы вектора.

Мне пришел в голову (тупой) вариант - просто распилить вектор, допустим, на 4 части и работать с каждой из частей,
получилось примерно следующее:

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
#include <vector>
#include "MyClass"
#include "f1"
#include "f2"
 
int main()
{
 
std::vector<MyClass> V_1;
std::vector<MyClass> V_2;
std::vector<MyClass> V_3;
std::vector<MyClass> V_4;
 
do
{
/********************************/
/* какая-то инициализация векторов */
/********************************/
 
//Работа с векторами 1 (функция f1 принимает вектор по ссылке 
//и работает с его элементами range-based циклом)
 
f1(V_1);
f1(V_2);
f1(V_3);
f1(V_4);
 
//Работа с векторами 2 (функция f2 принимает вектор по ссылке 
//и работает с его элементами range-based циклом)
 
f2(V_1);
f2(V_2);
f2(V_3);
f2(V_4);
 
}while (/*условие*/)
 
return 0;
}
Как я уже отмечал, параллельно выполнять операции f1 и f2 я не могу, так как f2 использует результат работы f1.
Но я могу засунуть выполнение, допустим, f1(V_1..4) в разные потоки и выполнять это дело параллельно.

Мой очень фиговый вариант:

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
#include <vector>
#include <thread>
#include "MyClass"
#include "f1"
#include "f2"
 
int main()
{
 
std::vector<MyClass> V_1;
std::vector<MyClass> V_2;
std::vector<MyClass> V_3;
std::vector<MyClass> V_4;
 
do
{
/********************************/
/* какая-то  инициализация векторов */
/********************************/
 
//Работа с векторами 1 (функция f1 принимает вектор по ссылке 
//и работает с его элементами range-based циклом)
 
std::thread t1([&]() { f1(V_1); });
std::thread t2([&]() { f1(V_2); });
std::thread t3([&]() { f1(V_3); });
f1(V_4);
 
t1.join();
t2.join();
t3.join();
 
//Работа с векторами 2 (функция f2 принимает вектор по ссылке 
//и работает с его элементами range-based циклом)
 
std::thread t4([&]() { f2(V_1); });
std::thread t5([&]() { f2(V_2); });
std::thread t6([&]() { f2(V_3); });
f2(V_4);
 
t4.join();
t5.join();
t6.join();
 
}while (/*условие*/)
 
return 0;
}
В принципе, такая краказябра даже работает. Но ее огромный недостаток - я в цикле постоянно открываю-закрываю кучу
потоков, и в результате вместо выигрыша в скорости от параллельных вычислений я получаю проигрыш в этой самой скорости
по сравнению даже со случаем тупого последовательного счета.

Я бы хотел (хотел бы я, ага...), чтобы у меня где-то в мэйне открывалось три потока, в которые я бы по мере необходимости
закидывал выполнение нужных функций. Но с библиотекой thread такого добиться не получается. Находил в интернетах
информацию, что можно использовать библиотеку pthread.h, но я так понял, что она типа устаревшая, я ее в моей VS-2017
даже подключить не могу.

Как быть?

Заранее благодарю за уделенное внимание)
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
12.05.2019, 19:06
Ответы с готовыми решениями:

Как распараллелить цикл while?
Доброго времени суток. При распараллелировании применять технологии Openmp. Было бы здорово, если бы ответ на вопрос, что в заглавии,...

Распараллелить цикл
Распараллелить цикл: For(i=2;i&lt;N;i++) For(j=2;i&lt;N;j++) A =A +A; #include &lt;iostream&gt; #include &lt;omp.h&gt; #include...

Многопоточное программирование
Добрый вечер, есть программа, которая ищет окно HWND Handle_ArcheAge; Handle_ArcheAge = FindWindow(L&quot;ArcheAge&quot;, NULL); //ищем...

45
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.05.2019, 15:36
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Юрий Мамонтов Посмотреть сообщение
Покажи, хотя бы, как ты их пишешь
Сейчас сделаю их так, как я их вижу в "атомарном виде"
Подозреваю, там изменяются одновремременно несколько переменных, например a, b и с
0
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
23.05.2019, 15:55  [ТС]
Подозреваю, там изменяются одновремременно несколько переменных, например a, b и с
Не а б и с, но вы правы, сразу несколько переменных, но все это под блокировкой, как я показал выше

А это проблема, что изменяются несколько переменных? Они ещё и к разным ячейкам mesh могут относиться
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.05.2019, 16:03
Цитата Сообщение от Юрий Мамонтов Посмотреть сообщение
Не а б и с, но вы правы, сразу несколько переменных, но все это под блокировкой, как я показал выше
Где?

Добавлено через 37 секунд
Цитата Сообщение от Юрий Мамонтов Посмотреть сообщение
А это проблема, что изменяются несколько переменных? Они ещё и к разным ячейкам mesh могут относиться
Если они взаимосвязаны, то должны изменяться синхронно

Добавлено через 3 минуты
В общем, скорее всего в классе Spher_1D_Area тебе понадобится мьютекс
0
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
23.05.2019, 16:08  [ТС]

Где?
C++
1
2
3
4
5
6
7
8
9
10
11
12
for (auto &i : V_1..procs)
   {
       /***ОПРЕДЕЛЕНИЕ ОБРАЩЕНИЯ К КОНКРЕТНОЙ ЯЧЕЙКЕ МАССИВА mesh***/
       p = /* Number */;//Вычислили номер ячейки сетки
      //Какие-то действия
       {
    std::lock_guard<std::mutex> Lock_f(m_f);
    ++mesh[p].Value;
        ++Contr_Sum;
        ++Count;
       }
   }
Вот здесь под Лок Гардом изменяются поля Ro, Quantity - в Ro прибавляется то, что было насчитано выше в цикле

Добавлено через 2 минуты

В общем, скорее всего в классе Spher_1D_Area тебе понадобится мьютекс
oleg-m1973, у меня объявлен мьютекс прямо в функции
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
23.05.2019, 16:24
Цитата Сообщение от Юрий Мамонтов Посмотреть сообщение
Вот здесь под Лок Гардом изменяются поля Ro, Quantity - в Ro прибавляется то, что было насчитано выше в цикле
Вообще, в таких задачах лучше, чтобы потоки вообще не записывали никаких общих данных. Т.е. не использовали никакие блокировки.
Пусть выполняют свои расчёты, сохраняют у себя промежуточные результаты, а когда закончат - пробегаешься по этим результатам (их очень мало ~кол-во процессоров) и делаешь окончательные расчёты - суммируешь и всё такое, тоже без блокировок.
0
6 / 6 / 0
Регистрация: 27.11.2016
Сообщений: 80
24.05.2019, 08:50  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Думаю, лучше не надо std::atomic это нифига не бесплатная штука.
Да уж, не бесплатная... Переделал только ОДНУ переменную в атомик - скорость упала раз в 10... Зато, надо сказать, оно работает!
То есть проблема с несовпадением контрольной суммы и длинами векторов решилась, теперь все работает четко. Но мееееееедленно....
Даже в однопоточном режиме быстрее..

Добавлено через 3 минуты
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Вообще, в таких задачах лучше, чтобы потоки вообще не записывали никаких общих данных. Т.е. не использовали никакие блокировки.
Пусть выполняют свои расчёты, сохраняют у себя промежуточные результаты, а когда закончат - пробегаешься по этим результатам (их очень мало ~кол-во процессоров) и делаешь окончательные расчёты - суммируешь и всё такое, тоже без блокировок.
Придется делать так, потому что другого выхода я не вижу: атомарные операции слишком затратны, а простые блокировки почему-то не вывозят.

В любом случае, oleg-m1973, спасибо огромное за помощь, за время обсуждения моего проекта я реально
многому научился) буду продолжать работать

Добавлено через 3 минуты
Termit779, спасибо за книгу, очень пригодилась при разбирательствах)
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.05.2019, 08:50
Помогаю со студенческими работами здесь

многопоточное программирование на с++
необходимо создать приложение которое с использованием thread (потоков) решит уравнение ну например дроюбное , то есть один поток решит...

Многопоточное программирование
Добрый день! Можете посоветовать кнгиги по многопоточному программированию на C++, не привязанные к ОС, использую Qt. Желательно, что...

Многопоточное программирование
Как я понимаю, есть много библиотек, с помощью которых мы можем использовать многопоточность. Чем они отличаются? Какая лучше? Почему? ...

Многопоточное программирование
Доброго времени суток! Пытался разобраться но не нашел понятных ответов на некоторые вопросы, поэтому, пожалуйста, не отсылайте к...

Не получается распараллелить цикл
Добрый день! В ходе опытов я выяснил, что распараллеливание цикла for с помощью OMP не приносит выигрыша во времени. Т.е. код...


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

Или воспользуйтесь поиском по форуму:
46
Ответ Создать тему
Новые блоги и статьи
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
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 На первой гифке отладочные линии отключены, а на второй включены:. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru