Russian Qt Forum

Qt => Вопросы новичков => Тема начата: nata267 от Апрель 11, 2014, 14:58



Название: Помогите распараллелить цикл
Отправлено: 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. Мне важен сам принцип распараллеливания. Как и где создавать потоки, мьютексы и т д как они обмпениваются значениями и переменными и.т.д.


Название: Re: Помогите распараллелить цикл
Отправлено: Vamireh от Апрель 11, 2014, 15:35
Разбиваете numIterations на N отрезков
Да хоть наследуетесь от QThread, в конструктор передаете индексы начала и конца отрезка, а также указатель на общие данные
В перегруженном run() выполянете нужный вам код для этого отрезка
Создаете N экземпляров этого класса
Для каждого вызываете start()
Для каждого вызываете wait()

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

Если очень грубо, то так.


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

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


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

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

Большое спасибо, попробую так


Название: Re: Помогите распараллелить цикл
Отправлено: OKTA от Апрель 11, 2014, 17:32
Чтобы не мучиться с QThread, посмотрите в сторону QtConcurrentRun и вообще в http://qt-project.org/doc/qt-4.8/threads-qtconcurrent.html


Название: Re: Помогите распараллелить цикл
Отправлено: Vamireh от Апрель 11, 2014, 17:46
Чтобы не мучиться с QThread, посмотрите в сторону QtConcurrentRun и вообще в http://qt-project.org/doc/qt-4.8/threads-qtconcurrent.html

Да, это гораздо проще, но:
Цитировать
Главное чтобы это было не автоматическое распараллеливание как в OpenMP. Мне важен сам принцип распараллеливания. Как и где создавать потоки, мьютексы и т д как они обмпениваются значениями и переменными и.т.д.


Название: Re: Помогите распараллелить цикл
Отправлено: nata267 от Апрель 12, 2014, 22:14
Может быть распараллеливать цикл - плохая идея? Может быть не любой цикл возможно распараллелить?


Название: Re: Помогите распараллелить цикл
Отправлено: Vamireh от Апрель 15, 2014, 05:50
Если каждая следующая итерация не зависит от предыдущих, то можно распараллелить. Однако не всегда это панацея, я лично встречал случаи когда два цикла последовательно работали быстрее, чем их запараллелить или их тела в один цикл вынести.
Также, например, я параллельными циклами ускорил одну программу раза в 4(на своей машине), но когда стали запускать на машинах клиента (не очень современное железо), то оказалось, что параллельная версия работает раз в 6 медленнее непараллельной, при этом всю систему вешает.
В общем, если все устраивает - не надо ничего не делать. (только ради интереса, самообразования и т.д.)


Название: Re: Помогите распараллелить цикл
Отправлено: Igors от Апрель 15, 2014, 10:15
...Любой цикл не важно.
...Инструмент не важен.
...Мне важен сам принцип распараллеливания.
В действительности все это важно. "Любой цикл" - совершенно неверный подход. "Кластер" должен быть приличным чтобы распараллеливание имело смысл. Если делать самому то выглядит примерно так

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

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

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




Название: Re: Помогите распараллелить цикл
Отправлено: OKTA от Апрель 15, 2014, 12:12
И добавлю к вышесказанному, что даже использование "автоматических" средств, как QtConcurrent и OpenMP не избавляет от необходимости использования средств синхронизации потоков, самостоятельной организации обмена данными между потоками и т.д. и т.д....