Russian Qt Forum
Ноябрь 26, 2024, 08:29 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Помогите распараллелить цикл  (Прочитано 6049 раз)
nata267
Гость
« : Апрель 11, 2014, 14:58 »

Друзья, не могу найти инфу как распараллелить цикл. Любой цикл не важно. Например, такой:

Код:
for (int it = 0; it < numIterations; it++) {
  for (int index = 0; index < cachedUserIDs.size(); index++) {
  long userId = cachedUserIDs[index];
  long itemId = cachedItemIDs[index];
float rating = cachedValues[index];
  updateParameters(userId, itemId, rating, currentLearningRate);
  }
  currentLearningRate *= learningRateDecay;
  }


Только начинаю изучать многопоточность. Инструмент не важен. Главное чтобы это было не автоматическое распараллеливание как в OpenMP. Мне важен сам принцип распараллеливания. Как и где создавать потоки, мьютексы и т д как они обмпениваются значениями и переменными и.т.д.
« Последнее редактирование: Апрель 11, 2014, 15:01 от nata267 » Записан
Vamireh
Гость
« Ответ #1 : Апрель 11, 2014, 15:35 »

Разбиваете numIterations на N отрезков
Да хоть наследуетесь от QThread, в конструктор передаете индексы начала и конца отрезка, а также указатель на общие данные
В перегруженном run() выполянете нужный вам код для этого отрезка
Создаете N экземпляров этого класса
Для каждого вызываете start()
Для каждого вызываете wait()

Если данные только читать, то можно как-то так. Если в данные надо что-то писать, то вдовесок в конструктор передаете указатель на мьютекс, а в методе run() перед записью его блокируйте, а после записи - разблокируйте.

Если очень грубо, то так.
Записан
Vamireh
Гость
« Ответ #2 : Апрель 11, 2014, 15:44 »

Ну или создаете просто класс, который делает этот цикл, а в параметре метода - начальный и конечный индекс. В начале метода блокируете мьютекс, в конце - разблокруйте.
Наследуетесь от того же QThread, передаете указатель на экземпляр первого класса. И в run вызваете его для нужного интервала.
Опять создаете сколько нужно потоков, для всех start() и wait().

Я бы скорее по такой схеме делал.
 
Записан
nata267
Гость
« Ответ #3 : Апрель 11, 2014, 15:59 »

Ну или создаете просто класс, который делает этот цикл, а в параметре метода - начальный и конечный индекс. В начале метода блокируете мьютекс, в конце - разблокруйте.
Наследуетесь от того же QThread, передаете указатель на экземпляр первого класса. И в run вызваете его для нужного интервала.
Опять создаете сколько нужно потоков, для всех start() и wait().

Я бы скорее по такой схеме делал.
 

Большое спасибо, попробую так
Записан
OKTA
Гость
« Ответ #4 : Апрель 11, 2014, 17:32 »

Чтобы не мучиться с QThread, посмотрите в сторону QtConcurrentRun и вообще в http://qt-project.org/doc/qt-4.8/threads-qtconcurrent.html
Записан
Vamireh
Гость
« Ответ #5 : Апрель 11, 2014, 17:46 »

Чтобы не мучиться с QThread, посмотрите в сторону QtConcurrentRun и вообще в http://qt-project.org/doc/qt-4.8/threads-qtconcurrent.html

Да, это гораздо проще, но:
Цитировать
Главное чтобы это было не автоматическое распараллеливание как в OpenMP. Мне важен сам принцип распараллеливания. Как и где создавать потоки, мьютексы и т д как они обмпениваются значениями и переменными и.т.д.
Записан
nata267
Гость
« Ответ #6 : Апрель 12, 2014, 22:14 »

Может быть распараллеливать цикл - плохая идея? Может быть не любой цикл возможно распараллелить?
Записан
Vamireh
Гость
« Ответ #7 : Апрель 15, 2014, 05:50 »

Если каждая следующая итерация не зависит от предыдущих, то можно распараллелить. Однако не всегда это панацея, я лично встречал случаи когда два цикла последовательно работали быстрее, чем их запараллелить или их тела в один цикл вынести.
Также, например, я параллельными циклами ускорил одну программу раза в 4(на своей машине), но когда стали запускать на машинах клиента (не очень современное железо), то оказалось, что параллельная версия работает раз в 6 медленнее непараллельной, при этом всю систему вешает.
В общем, если все устраивает - не надо ничего не делать. (только ради интереса, самообразования и т.д.)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Апрель 15, 2014, 10:15 »

...Любой цикл не важно.
...Инструмент не важен.
...Мне важен сам принцип распараллеливания.
В действительности все это важно. "Любой цикл" - совершенно неверный подход. "Кластер" должен быть приличным чтобы распараллеливание имело смысл. Если делать самому то выглядит примерно так

- завести N ниток для параллельной работы, которые пока спят
- разбить задачи цикла на кучки, в простейшем случае дать каждой рабочей нитке примерно одинаковое число задач
- запустить каждую рабочую нитку дав ей "свои" задачи
- дождаться окончания работы каждой рабочей и усыпить ее

Реализовать это непросто, напр прямолинейное усыпление/пробуждение ниток может оказаться неприемлемо медленным. Поэтому надо подбирать инструмент. Я пользуюсь OpenMP и очень доволен. Qt аналог - QtConcurrent.

По поводу мутексов, обмена данными и.т.п. - это "синхронизация", отношение к распараллеливанию имеет косвенное.


Записан
OKTA
Гость
« Ответ #9 : Апрель 15, 2014, 12:12 »

И добавлю к вышесказанному, что даже использование "автоматических" средств, как QtConcurrent и OpenMP не избавляет от необходимости использования средств синхронизации потоков, самостоятельной организации обмена данными между потоками и т.д. и т.д....
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.048 секунд. Запросов: 22.