make_chunks <- function(n_x, n_workers, scheduling = 1L, chunk_size = NULL) {
if (is.null(chunk_size)) {
n_chunks <- compute_n_chunks_from_scheduling(scheduling, n_x, n_workers)
} else {
n_chunks <- compute_n_chunks_from_chunk_size(chunk_size, n_x)
}
parallel::splitIndices(n_x, n_chunks)
}
compute_n_chunks_from_scheduling <- function(scheduling, n_x, n_workers) {
if (is.logical(scheduling)) {
compute_n_chunks_from_scheduling_logical(scheduling, n_x, n_workers)
} else if (is.integer(scheduling)) {
compute_n_chunks_from_scheduling_integer(scheduling, n_x, n_workers)
} else if (identical(scheduling, Inf)) {
n_x
}
}
compute_n_chunks_from_scheduling_logical <- function(scheduling, n_x, n_workers) {
# One future per element of `x`
if (is_false(scheduling)) {
return(n_x)
}
# One future per worker (if there are enough elements in `x`)
if (n_workers > n_x) {
n_x
} else {
n_workers
}
}
# Treat:
# N chunks / 1 workers = scheduling
# So:
# N chunks = (N chunks / 1 workers) * N workers
compute_n_chunks_from_scheduling_integer <- function(scheduling, n_x, n_workers) {
if (n_workers > n_x) {
n_workers <- n_x
}
n_chunks <- scheduling * n_workers
# Catch `scheduling == 0L`
if (n_chunks < 1L) {
n_chunks <- 1L
}
if (n_chunks > n_x) {
n_chunks <- n_x
}
n_chunks
}
# From `future.apply:::makeChunks()`, with description of:
# "Same definition as parallel:::staticNChunks() in R (>= 3.5.0)"
compute_n_chunks_from_chunk_size <- function(chunk_size, n_x) {
max(1L, ceiling(n_x / chunk_size))
}
# ------------------------------------------------------------------------------
# Custom ordering can be used to process the elements of `x` in. It is
# extracted from `scheduling` or `chunk_size` as the `"ordering"` attribute.
make_order <- function(n_x, scheduling, chunk_size) {
if (is.null(chunk_size)) {
ordering <- attr(scheduling, "ordering", exact = TRUE)
compute_order(ordering, n_x, "scheduling")
} else {
ordering <- attr(chunk_size, "ordering", exact = TRUE)
compute_order(ordering, n_x, "chunk_size")
}
}
compute_order <- function(ordering, n_x, arg) {
if (is.null(ordering)) {
return(NULL)
}
if (is.character(ordering) && identical(ordering, "random")) {
order <- sample_n_with_reset(n_x)
} else if (is.integer(ordering)) {
order <- ordering
} else if (is.double(ordering)) {
order <- vctrs::vec_cast(ordering, integer(), x_arg = "ordering")
} else if (is.function(ordering)) {
order <- ordering(n_x)
} else {
abort(paste0(
"Unknown type of `", arg, "` attribute, `ordering`. The attribute must ",
"be a character string, an integer, or a function."
))
}
if (!is.integer(order)) {
abort("Order computed from `ordering` attribute must be an integer.")
}
if (length(order) != n_x) {
abort("Order computed from `ordering` must have length equal to `.x`.")
}
order
}
# Reset on exit to not modify randomness state
sample_n_with_reset <- function(n) {
oseed <- .GlobalEnv$.Random.seed
on.exit({
if (is.null(oseed)) {
rm(list = ".Random.seed", envir = .GlobalEnv, inherits = FALSE)
} else {
.GlobalEnv$.Random.seed <- oseed
}
})
sample.int(n = n, size = n, replace = FALSE)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.