Джулия: Предаване на данни между съпрограми (задачи)

Опитах се да накарам две задачи (корутини) да си сътрудничат, но без резултат. По-долу е това, което имам. Никога не виждам printlns от функциите източник или приемник и извикването на wait() изглежда виси завинаги. Също така се опитах да направя задачата p (източник) глобална променлива, вместо да я предам на sink() като аргумент, но и това не изглежда да работи (дори когато я декларирам вътре sinke() като глобална.

Това е нещо, което открих, че мога да правя много лесно с канали и goroutines в Go.

Също така експериментирах с извикване на yieldto() във функциите source() и sink(), но все още изглежда, че завършвам в задънена улица.

Някой с пример за множество задачи, споделящи данни по някакъв начин? В идеалния случай бих имал конвейер или дълга верига от задачи.

Благодаря ви предварително за помощта.

println("Hello")

function source()
  println("source start")
  produce("start")
  produce("stop")
end

function sink(p::Task)
  println("sink start")
  println(consume(p))
  println(consume(p))
end


a = Task( source )
b = Task( () -> sink(a)   )

wait(b)
wait(a)

println("Goodbye")

person Richard Palmer    schedule 22.04.2014    source източник


Отговори (1)


В Julia създаването на задача не планира автоматично тази задача. Функцията за изчакване също не планира, така че в крайна сметка се оказвате в задънена улица. Това е голяма разлика от Go, където инструкцията go се грижи за цялото планиране вместо вас. В Julia трябва да свършите малко повече работа. По-конкретно използвайте макросите @sync и @async, за да го улесните.

@sync begin # @sync will wait for all the contained tasks to terminate.
   a = @async source() # @async will create and schedule a task for you automatically
   @async sink(a)
 end

Ще забележите обаче, че това също не прекратява. Всички разпечатки се случват, но задачата не се прекратява. Причината е, че @sync чака задача a да завърши, но задача a не е планирана. Добавете окончателно потребление или график към вашата функция за поглъщане, за да принудите задача a да бъде планирана за последен път, за да може да прекрати. Или още по-добре използвайте for цикъл на задачата, така че винаги да я изчерпвате.

println("Hello")

function source()
  println("source start")
  produce("start")
  produce("stop")
  println("source end")
end

function sink(p::Task)
  println("sink start")
  for s in p
    println(s)
  end
  println("sink end")
end

@sync begin
   a = @async source()
   @async sink(a)
 end

println("Goodbye")

Задачите на Джулия са съвместно планирани, което на практика означава, че трябва да гарантирате, че всяка задача ще бъде планирана сами. Времето за изпълнение няма да го направи вместо вас. За щастие макросите @sync и @async правят повечето от това вместо вас.

person Jeremy Wall    schedule 22.04.2014
comment
Страхотен! Благодаря за ясния отговор. Виждам, че julia дава много по-фин контрол върху съпрограмите. Оценявам вашата помощ. - person Richard Palmer; 22.04.2014