Skip to content

Instantly share code, notes, and snippets.

@jrosell
Last active February 13, 2024 15:32
Show Gist options
  • Save jrosell/7a38c8731a4002425e5e39bce35fd0e8 to your computer and use it in GitHub Desktop.
Save jrosell/7a38c8731a4002425e5e39bce35fd0e8 to your computer and use it in GitHub Desktop.
# preallocates memory.
fmat <- function(n) {
res <- matrix(NA, n, n)
for (i in 1:n) {
res[i, ] <- runif(n)
}
res
}
# rbind each time
frbind <- function(n) {
res <- vector()
for (i in 1:n) {
res <- rbind(res, runif(n))
}
res
}
# growing the final matrix in chunks
fchunks <- function(n, csize = 10) {
chunk <- matrix(NA, csize, n)
res <- vector()
for (i in 1:n) {
if (i %% csize == 0) {
chunk[csize, ] <- runif(n)
res <- rbind(res, chunk)
chunk <- matrix(NA, csize, n)
} else {
chunk[i %% csize, ] <- runif(n)
}
}
res[!is.na(res[, 1]), ]
}
# grow list which is converted to a matrix at the end.
flist <- function(n) {
res <- list()
for (i in 1:n) {
res[[length(res) + 1]] <- runif(n)
}
do.call(rbind, res)
}
# Using cbind might, given that R mostly deals in columns.
fcbind <- function(n) {
res <- vector()
for (i in 1:n) {
res <- cbind(res, runif(n))
}
t(res)
}
fpurrr <- function(n) {
x <- purrr::map(1:n, \(x) runif(n))
len <- length(x)
res <- x |> purrr::list_c()
dim(res) <- c(len, len)
res
}
fmatrixbyrow <- function(n) {
x <- lapply(1:n, function(x) runif(n))
len <- length(x)
res <- matrix(as.numeric(unlist(x)), nrow = len, byrow = TRUE)
res
}
fpurrr2 <- function(n) {
res <- purrr::map(1:n, \(x) runif(n))
do.call(rbind, res)
}
flist2 <- function(n) {
res <- list()
for (i in 1:n) {
res[[length(res) + 1]] <- runif(n)
}
len <- length(res)
res <- res |> purrr::list_c()
dim(res) <- c(len, len)
res
}
flist3 <- function(n) {
res <- list()
for (i in 1:n) {
res[[length(res) + 1]] <- runif(n)
}
len <- length(res)
res <- matrix(as.numeric(unlist(res)), nrow = len, byrow = TRUE)
res
}
fvec0 <- function(n) {
res <- vector(mode = "list")
for (i in 1:n) {
res[[length(res) + 1]] <- runif(n)
}
do.call(rbind, res)
}
fvec2 <- function(n) {
res <- vector(mode = "list")
for (i in 1:n) {
res[[length(res) + 1]] <- runif(n)
}
len <- length(res)
res <- res |> purrr::list_c()
dim(res) <- c(len, len)
res
}
n <- 1000
bench <- microbenchmark::microbenchmark(
fmat(n),
frbind(n),
fcbind(n),
fchunks(n, csize = 100),
flist(n),
fpurrr(n),
fpurrr2(n),
fmatrixbyrow(n),
flist2(n),
flist3(n),
times = 30, unit = "ms"
)
bench |> print()
n <- 10000
bench2 <- microbenchmark::microbenchmark(
flist(n),
flist2(n),
flist3(n),
times = 30, unit = "ms"
)
n <- 10000
bench3 <- bench::mark(
fmat(n),
flist(n),
flist2(n),
fvec0(n),
fvec2(n),
min_iterations = 30, check = FALSE, time_unit = "ms", filter_gc = FALSE
)
bench3 |> print()
@jrosell
Copy link
Author

jrosell commented Feb 13, 2024

Here the results I get using n=1000

Unit: milliseconds
                    expr        min         lq       mean     median         uq        max neval cld
                 fmat(n)   17.61833   19.38959   24.20696   22.66409   26.34475   38.67556    30 a  
               frbind(n) 2391.89174 2566.30033 2914.33888 2753.04068 3209.01297 4149.40350    30  b 
               fcbind(n)  749.18951  790.39829  984.90949  909.43991 1088.54513 1584.23218    30   c
 fchunks(n, csize = 100)   42.00765   50.13191   56.70839   55.79666   61.21388   75.67504    30 a  
                flist(n)   16.61024   17.99313   22.56021   19.73917   22.75390   71.26850    30 a  
               fpurrr(n)   16.32769   17.50399   20.29709   19.03965   21.44372   30.55751    30 a  
              fpurrr2(n)   16.89476   18.06340   27.64374   21.43626   26.19305   94.35030    30 a  
         fmatrixbyrow(n)   17.93795   19.71058   22.89435   20.75255   24.51895   46.99049    30 a  
               flist2(n)   15.42096   17.10790   22.55404   19.09571   25.64185   69.56023    30 a  
               flist3(n)   17.79746   19.12523   26.24173   23.77993   28.84740   53.79007    30 a
``

@jrosell
Copy link
Author

jrosell commented Feb 13, 2024

Here the results I get using n=10000 for the most promising options using a for loop and without preacollacting memory.

Unit: milliseconds
      expr      min       lq     mean   median       uq      max neval cld
  flist(n) 2165.015 2564.815 2939.605 2819.418 3165.993 5139.394    30 a  
 flist2(n) 1444.778 1619.172 1822.930 1767.477 2028.077 2371.247    30  b 
 flist3(n) 2632.312 3194.872 3491.858 3451.352 3705.835 4765.866    30   c

@jrosell
Copy link
Author

jrosell commented Feb 13, 2024

Here the results, including memory allocation using n=10000

  expression   min median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time result memory     time            gc      
  <bch:expr> <dbl>  <dbl>     <dbl> <bch:byt>    <dbl> <int> <dbl>      <dbl> <list> <list>     <list>          <list>  
1 fmat(n)    2864.  3057.     0.322    2.26GB    0.633    30    59     93221. <NULL> <Rprofmem> <bench_tm [30]> <tibble>
2 flist(n)   2613.  2672.     0.364    1.52GB    0.462    30    38     82327. <NULL> <Rprofmem> <bench_tm [30]> <tibble>
3 flist2(n)  1737.  1972.     0.453    1.52GB    0.726    30    48     66155. <NULL> <Rprofmem> <bench_tm [30]> <tibble>
4 fvec0(n)   2567.  2899.     0.318    1.52GB    0.637    30    60     94193. <NULL> <Rprofmem> <bench_tm [30]> <tibble>
5 fvec2(n)   1748.  2036.     0.478    1.52GB    0.956    30    60     62766. <NULL> <Rprofmem> <bench_tm [30]> <tibble>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment