Solution for interactive layouting algorithm

28 views
Skip to first unread message

Marek Berith

unread,
Mar 28, 2023, 10:22:29 AM3/28/23
to Legion Users

Dear community


I apologize for the long e-mail, but my questions need some introduction. 


For my bachelor's thesis I worked on a distributed graph visualization tool that uses the Fruchterman-Reingold’s force-based graph layouting algorithm (FR) implemented in Regent. I am currently evaluating whether to continue the implementation in Regent.  


Our solution is split into a Regent backend that iteratively calculates the graph layout (calculates new node positions) and a separate rendering frontend that communicates with the backend using sockets. 


We needed a multi-threaded backend: we needed at least one thread for network communication in combination with Regent tasks that do the graph layouting calculations.


Our solution is that we create a new thread in Effil that communicates with Regent using Effil channels. In the newly started Effil thread, we created socket communication with the frontend using lzmq sockets. Then we call regentlib.start.


_listen = effil.thread(listen)()                 

regentlib.start(main)


The problem with this implementation is that in order to communicate between Regent and Effil, we have to pass a Lua table to the Effil channel (user data is not allowed). Therefore, we dynamically allocate a C array in Terra and copy the Regent regions within the task into that array. Then, in the Terra function, we copy the C array into a Effil table and place the Effil table into a channel. This solution requires creating many copies of the same data and is therefore a performance problem.


So the question is how to efficiently share Regent data (the graph’s nodes and edges stored in Regent regions) to code outside of Regent tasks, e.g.:

  • How to stream intermediate results from Regent tasks via network sockets to external network processes ?

  • How to receive input data from external processes via network sockets into continuously running Regent tasks ?


Also, our question is how to implement interactive applications in Regent. Or is Regent only aimed for “batch processing” of large datasets in HPC environments?


Thank you for any help,

Marek

Legion Users_ Code.txt

Elliott Slaughter

unread,
Mar 29, 2023, 12:52:06 PM3/29/23
to Marek Berith, Legion Users
Let me prefix this by saying that the answer is the same whether you're asking about Regent or another language using Legion. I'll write Legion below because it's more of a runtime issue than a compiler one, but I'm including Regent in this.

Overall, you're right in observing that Legion is targeted more for batch processing than interactive. That's not to say you can't write interactive programs (e.g., we have Jupyter notebook support), but it's more work and has to be done with some care. You'll need to know more about how the runtime works and make sure you don't do anything bad.

I would avoid creating additional threads, because those live outside of Legion's control. Instead I would do something like:

For output: I'd allocate the socket and store it in a region. Then each time I want to send data out to the external process, I'd use a task (read-write on the socket region and read-only on whatever data is to be sent). You can use the mapper, or a processor constraint on the task, to ensure that it runs exactly where you want it to.

For input: this is a bit trickier because it depends on whether you want to avoid blocking on input or not. If you're willing to block, then it's easy to do the above in reverse: launch a task which reads the socket and have that task return the data. If you want to avoid blocking, probably the easiest way to do that is to still launch the task, but write the task body such that if no data is available, it does not block. Then the task can just return an empty future and the program will know no new data is available.

Using ZMQ vs BSD sockets vs whatever is fine and makes no difference to us.

One last note: I would avoid using any Lua constructs in the Regent code. The Lua context that exists when you compile your Regent code is not guaranteed to exist when the program runs, and on top of it, unless you're very careful the Lua code may not be thread-safe.

Hope that helps.

--
You received this message because you are subscribed to the Google Groups "Legion Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to legionusers...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/legionusers/30c24ce4-bf6f-410b-ba47-09e005ab2ce2n%40googlegroups.com.


--
Elliott Slaughter

"Don't worry about what anybody else is going to do. The best way to predict the future is to invent it." - Alan Kay

Yamajala, Seshu

unread,
Mar 31, 2023, 2:52:46 AM3/31/23
to slau...@cs.stanford.edu, marek...@outlook.sk, legio...@googlegroups.com
I think also in order to avoid extra copies you would want to use raw pointers. This is only safe to do within a leaf task. See the cholesky example:

Reply all
Reply to author
Forward
0 new messages