Concurrent code execution with maximum flexibility and automatic resolution
{mirai} is a minimalist async evaluation framework for R.
未来 みらい mirai is Japanese for ‘future’.
mirai provides an extremely simple and lightweight method for concurrent / parallel code execution.
Since the original ‘introduction’ article two months ago, mirai is currently in its fourth incarnation, hence the need for a re-introduction. In this time, the package has also featured in RStudio’s Top 40 New CRAN Packages for February 2022.
We outline some of the main visible innovations below, but suffice to say that the backend (especially the code behind the nanonext package) has been very much optimised over the course of this time as well.
Originally, the package revolved around 2 functions -
eval_mirai()
and call_mirai()
. Those are still
there, and work the same way - however the package has managed to become
even more minimalist with only one being required now.
This one function is simply called mirai()
.
(eval_mirai()
maps to it as an alias.)
Using mirai()
returns a ‘mirai’ object immediately.
A mirai evaluates an arbitrary expression asynchronously, resolving automatically upon completion.
Yes, resolving automatically, hence call_mirai()
is no
longer needed (although it can still sometimes be useful to call and
wait for results).
The evaluated result of a mirai is stored at $data
. If
the asynchronous operation has yet to complete then this will return an
‘unresolved’ logical NA value. That is an actual NA value of type
logical classed as ‘unresolved’.
As soon as it resolves, then $data
will return the
actual value of the evaluated expression.
Enter unresolved()
, a helper function that can be used
in control flow statements to allow you to do things before and after
resolution of a mirai. This means that you never have to actually just
wait on a mirai.
The code output below probably serves as a better demonstration than a lengthy explanation:
'unresolved' logi NA
while (unresolved(m)) {
cat("unresolved\n")
Sys.sleep(1)
}
unresolved
unresolved
m$data
[1] TRUE
'unresolved' logi NA
repeat {
unresolved(m) || break
cat("unresolved\n")
Sys.sleep(1)
}
unresolved
unresolved
m$data
[1] TRUE
You may have noticed in the above examples that the expression being
evaluated was wrapped in { }
. mirai supports this being an
arbitrarily-long, possibly multi-line expression. Similarly there is no
limit to the number of arguments supplied to the call.
To supply objects that are already present in the calling environment, these may simply be passed in as per the below:
[,1] [,2]
[1,] 1 3
[2,] 2 4
m <- mirai({
x <- t(x)
as.data.frame(x)
}, x = mat)
call_mirai(m)$data
V1 V2
1 1 2
2 3 4
The default behaviour is to just spin up background processes as required. This offers maximum simplicity and ease of use - no need to consider the backend at all.
First of all this is remarkable in itself, in that mirai simply works on all platforms R can be installed - across Linux, Windows, Mac, Solaris etc. and this is down to the cross-platform support built in to the underlying NNG C library that nanonext provides a binding for.
Second, the startup time is relatively tiny as a completely clean background R process with ‘–vanilla’ settings is started each time. However for the highest performance applications, there is now the option to start up a set number of processes (daemons) upfront, and these will be ready to wait for instructions, achieveing even more minimal latency.
Setting daemons is as simple as:
daemons(8)
#> [1] 8
.. and 8 daemons are created.
We presented above 4 key updates for the fourth version of mirai (v0.4.0). We invite you to try it out for yourselves:
install.packages("mirai")
Any issues/comments please feed back at Github: https://github.com/shikokuchuo/mirai
Package website: https://shikokuchuo.net/mirai/
For attribution, please cite this work as
shikokuchuo (2022, April 18). shikokuchuo{net}: Re-introducing mirai - a minimalist async evaluation framework for R. Retrieved from https://shikokuchuo.net/posts/18-reintroducing-mirai/
BibTeX citation
@misc{shikokuchuo2022re-introducing, author = {shikokuchuo, }, title = {shikokuchuo{net}: Re-introducing mirai - a minimalist async evaluation framework for R}, url = {https://shikokuchuo.net/posts/18-reintroducing-mirai/}, year = {2022} }