coolbutuseless / nara

nativeRaster tools for R
https://coolbutuseless.github.io/package/nara/index.html
Other
62 stars 4 forks source link

x2 speedup in colour_to_integer mapping when replacing nara::colour_to_integer() with farver::encode_native() #6

Closed zeehio closed 5 months ago

zeehio commented 2 years ago

Thanks for letting me discover nativeRaster objects through your nara package. They are blazingly fast!

Just in case you are looking for further optimizations, my benchmark on nara::colour_to_integer() with both a 512 long vector and a 10 million vector shows that farver::encode_native() is close to twice as fast.

with a 10 million long vector:

# Generate a vector of colours:
ramp <- scales::colour_ramp(c("red", "blue"))
large_colormap <- ramp(runif(1E7))
head(large_colormap)
#> [1] "#CA0087" "#EA004B" "#F90021" "#E00060" "#D60074" "#BE0099"
# Benchmark
bench::mark(farver = {farver::encode_native(large_colormap)}, nara = {nara::colour_to_integer(large_colormap)})
#> # A tibble: 2 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 farver        284ms    284ms      3.53    38.2MB     3.53
#> 2 nara          603ms    603ms      1.66    38.2MB     0

With a 512 long vector, similar behaviour:

ramp <- scales::colour_ramp(c("red", "blue"))
small_colormap <- ramp(runif(512))
head(small_colormap)
#> [1] "#DC0069" "#8E00CD" "#D30078" "#F70027" "#D50076" "#4800F4"
bench::mark(farver = {farver::encode_native(small_colormap)}, nara = {nara::colour_to_integer(small_colormap)})
#> # A tibble: 2 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 farver       13.3µs   15.1µs    63080.    8.53KB        0
#> 2 nara         27.4µs   29.8µs    31544.   50.84KB        0

Created on 2022-09-06 by the reprex package (v2.0.1)

tomwenseleers commented 1 year ago

Somewhat related: if you are interested in converting a matrix with intensity values to a native raster given a certain colour palette, I noticed that

# function to convert matrix to nativeRaster given a colour palette col
mat2natrast = function(mat, col) {
  idx = findInterval(mat, seq(0, 1, length.out = length(col)))
  colors = col[idx]
  natrast = nara::raster_to_nr(t(matrix(colors, ncol = ncol(mat), nrow = nrow(mat), byrow = TRUE)))
  return(natrast)
}

would be more than twice as fast than

# alt function to convert matrix to nativeRaster given a colour palette col
# this was somehow slower than function above
mat2natrast2 = function(mat, col) {
  idx = findInterval(mat, seq(0, 1, length.out = length(col)))
  colints = farver::encode_native(col[idx]) # hex colours as integers representing RGBA
  # colints = nara::colour_to_integer(col[idx]) # this would be 2x slower still
  natrast = t(matrix(colints, ncol = ncol(mat), nrow = nrow(mat), byrow = TRUE))
  class(natrast) = "nativeRaster"
  return(natrast)
}

Might be worth perhaps of including a computationally efficient function to convert a given numeric matrix to nativeRaster, given a certain colour palette, as this will be a common usage case of nara & potentially display it... This could be the basis for a fast version of the image() function, which could also be nice...

coolbutuseless commented 5 months ago

colour_to_integer() is now faster than it was, and on par with {farver}


the introduction matrix_to_nr() now addresses @tomwenseleers issue.