There are good synchronization primitives for Tasks, and a bit for threads, 
but not much for parallel processes. (One could use named system semaphores 
on Linux and Windows, but there's no Julia wrapper yet AFAIK.)
I also found management of parallel processes confusing, and good 
nontrivial examples are not obvious.  So here's my humble offering:
https://gist.github.com/RalphAS/2a37b1c631923efa30ac4a7f02a2ee9d

(I just happen to be working on some synchronization problems this month; 
if a real expert has a better solution, let's hear it.)

On Friday, October 14, 2016 at 3:19:25 PM UTC-4, Zachary Roth wrote:
>
> Thanks for the reply and suggestion, Ralph.  I tried to get this working 
> with semaphores/mutexes/locks/etc.  But I've not been having any luck.
>
> Here's a simplified, incomplete version of what I'm trying to do.  I'm 
> hoping that someone can offer a suggestion if they see some sample code.  
>
> function localfunction()
>     files = listfiles()
>     locks = [Threads.SpinLock() for _ in files]
>     ranges = getindexranges(length(files))
>
>     pmap(pairs(ranges)) do rows_and_cols
>         rows, cols = rows_and_cols
>         workerfunction(files, locks, rows, cols)
>     end
> end
>
> function workerfunction(files, locks, rows, cols)
>     data = kindofexpensive(...)
>     pairs = pairs(rows, cols)
>     
>     @sync for idx in unique([rows; cols])
>         @async begin
>             lock(locks[idx])
>             updatefile(files[idx], data[idx])
>             unlock(locks[idx])
>         end
>     end
> end
>
> This (obviously) does not work.  I think that the problem is that the 
> locks are being copied when the function is spawned on each process.  I've 
> tried wrapping the locks/semaphores in Futures/RemoteChannels, but that 
> also hasn't worked for me.
>
> I found that I could do the sort of coordination that I need by starting 
> Tasks on the local process.  More specifically, each file would have an 
> associated Task to handle the coordination between processes.  But this 
> only worked for me in a simplified situation with the Tasks being declared 
> globally.  When I tried to implement this coordination within localfunction 
> above, I got an error (really a bunch of errors) that said that a running 
> Task cannot be serialized.
>
> Sorry for the long post, but I'm really hoping that someone can help me 
> out.  I have a feeling that I'm missing something pretty simple.
>
> ---Zachary
>
>
>
>
> On Tuesday, October 11, 2016 at 10:15:06 AM UTC-4, Ralph Smith wrote:
>>
>> You can do it with 2 (e.g. integer) channels per worker (requests and 
>> replies) and a task for each pair in the main process. That's so ugly I'd 
>> be tempted to write an
>>  interface to named system semaphores. Or just use a separate file for 
>> each worker.
>>
>> On Monday, October 10, 2016 at 11:09:39 AM UTC-4, Zachary Roth wrote:
>>>
>>> Hi, everyone,
>>>
>>> I'm trying to save to a single file from multiple worker processes, but 
>>> don't know of a nice way to coordinate this.  When I don't coordinate, 
>>> saving works fine much of the time.  But I sometimes get errors with 
>>> reading/writing of files, which I'm assuming is happening because multiple 
>>> processes are trying to use the same file simultaneously.
>>>
>>> I tried to coordinate this with a queue/channel of `Condition`s managed 
>>> by a task running in process 1, but this isn't working for me.  I've tried 
>>> to simiplify this to track down the problem.  At least part of the issue 
>>> seems to be writing to the channel from process 2.  Specifically, when I 
>>> `put!` something onto a channel (or `push!` onto an array) from process 2, 
>>> the channel/array is still empty back on process 1.  I feel like I'm 
>>> missing something simple.  Is there an easier way to go about coordinating 
>>> multiple processes that are trying to access the same file?  If not, does 
>>> anyone have any tips?
>>>
>>> Thanks for any help you can offer.
>>>
>>> Cheers,
>>> ---Zachary
>>>
>>

Reply via email to