Параллельный код для асинхронных множественных вычислений в Julia

Я знаю, что это могло быть задано в прошлом, но я абсолютный новичок в Джулии.

У меня есть простой код в Джулии, который я хотел бы запустить параллельно.

#--Two Calculations during the Loop--

vt_0=0
ct_0=0

for i=1:10

 #--Calculation vt_1
 vt_1=max(rand(1:i),vt_0,ct_0)


 #--Calculation ct_1
 ct_1=min(rand(1:i),vt_0,ct_0)

 ct_0=ct_1
 vt_0=vt_1

end

Как видите, вычисление vt_1 и ct_1 может быть выполнено одновременно (или в одном и том же цикле без ожидания вычисления ct_1 вычисления vt_1).

Может ли кто-нибудь помочь мне изменить этот код для параллельной работы? Должен ли я загружать какой-либо скрипт/библиотеку Julia? (У меня гораздо больший и сложный код для динамического программирования, но суть та же.)

заранее спасибо


person Gunnar    schedule 13.10.2017    source источник
comment
Возможно, вы захотите изменить заголовок, так как под распараллеливанием базового цикла люди догадаются, что вы имеете в виду каждую итерацию цикла на отдельном ядре, тогда как (я понимаю) вы действительно хотите просто запустить несколько выражений асинхронно, а затем дождаться всех ответов .   -  person Alexander Morley    schedule 13.10.2017
comment
Сделанный. Надеюсь, теперь это имеет больше смысла.   -  person Gunnar    schedule 13.10.2017


Ответы (2)


Это то, что вы ищите? Вероятно, быстрее не использовать анонимную функцию, как у меня здесь, а иначе.

addprocs(2)        
vt_0 = 0; ct_0 = 0;
for i=1:10
  #--Calculation vt_1
  vt_1 = remotecall((x,y)->max(rand(1:i),x,y), 2, vt_0, ct_0)

  #--Calculation ct_1
  ct_1 = remotecall((x,y)->min(rand(1:i),x,y), 3, vt_0, ct_0)

  ct_0 = fetch(ct_1)
  vt_0 = fetch(vt_1)
end

Или без анонимных функций:

addprocs(2)
@everywhere minrand(i,x,y) = min(rand(1:i),x,y)
@everywhere maxrand(i,x,y) = max(rand(1:i),x,y)
vt_0 = 0; ct_0 = 0; 

for i=1:10 
  #--Calculation vt_1
  vt_1 = remotecall(maxrand, 2, i, vt_0, ct_0)

  #--Calculation ct_1
  ct_1 = remotecall(minrand, 3, i, vt_0, ct_0)

  ct_0 = fetch(ct_1)
  vt_0 = fetch(vt_1)
end
person Alexander Morley    schedule 13.10.2017
comment
Именно то, что я искал! Большое спасибо. - person Gunnar; 13.10.2017
comment
Привет! Я пробовал эти две параллельные версии (с разными параметрами), и время, необходимое для параллельного расчета, значительно больше, чем последовательное. Например, изменив количество итераций с 10 на 10000, в моем простом последовательном коде для завершения требуется в среднем 0,010 секунды, а в параллельном коде (фактически второй, который вы предоставляете) для завершения требуется в среднем 27 секунд. . Как вы думаете, я делаю что-то не так? Возможно, я что-то упускаю? Я использую Jupyter Notebook на всякий случай. ТИА! - person Gunnar; 14.10.2017
comment
Таким образом, 27 секунд кажутся слишком большими, поэтому там может быть что-то еще, но ... всегда будут накладные расходы (связанные с вводом-выводом) для отправки данных в/из другого процессора, что в этом случае перевешивает выигрыш от разделения вычислений. (если бы у вас было, скажем, 20 выражений, которые можно было бы разделить в каждом цикле, тогда история могла бы быть другой). Вам возможно повезет больше, если вы попытаетесь использовать многопоточность — в противном случае используйте то время, которое подскажет вам самое быстрое! - person Alexander Morley; 16.10.2017
comment
(и или вы можете задать отдельный вопрос о скорости вышеперечисленного на SO, вы, вероятно, найдете кого-то, кто знает больше, чем я!) - person Alexander Morley; 16.10.2017
comment
Благодарю вас! Действительно, я обнаружил больше проблем с двойной обработкой, сохраню их для другого поста. - person Gunnar; 16.10.2017

Мне будет любопытно, есть ли на это действительно хороший ответ. Обычно параллельное выполнение в Julia является частью Base, поэтому для него не нужна специальная библиотека. Но ваш вариант использования не типичен для параллельного выполнения IIUC. Обычно параллельный цикл for повторяет вызов одного и того же выражения с разными значениями, т. е. вы выполняете выражение, связанное с i = 1 на одном ядре, i = 2 на другом, и объединяете результаты. Здесь есть хорошее объяснение: https://docs.julialang.org/en/latest/manual/parallel-computing/#Parallel-Map-and-Loops-1

Вы предлагаете запускать разные части программы (разные выражения) на разных ядрах. РЕДАКТИРОВАТЬ: в ответе Александра есть хорошее описание того, как это сделать.

person Michael K. Borregaard    schedule 13.10.2017
comment
Я что-то упускаю? Или смысл в том, что я написал? - person Alexander Morley; 13.10.2017
comment
AFAICS это имеет смысл :-) Я вижу, что могут быть варианты использования для чего-то подобного. - person Michael K. Borregaard; 13.10.2017