Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
性能良好的charToRaw矢量化版本_R_Vectorization - Fatal编程技术网

性能良好的charToRaw矢量化版本

性能良好的charToRaw矢量化版本,r,vectorization,R,Vectorization,我想从字符向量中获取原始字节向量(应用加密函数,该函数要求原始字节作为data.table列的所有值的输入) charToRaw不进行向量化,但只处理向量的第一个元素: x <- c("hello", "my", "world") charToRaw(x) # Warning message: # In charToRaw(x) : argument should be a character vector of length 1 # all but the first element w

我想从字符向量中获取原始字节向量(应用加密函数,该函数要求原始字节作为
data.table
列的所有值的输入)

charToRaw
不进行向量化,但只处理向量的第一个元素:

x <- c("hello", "my", "world")
charToRaw(x)
# Warning message:
# In charToRaw(x) : argument should be a character vector of length 1
# all but the first element will be ignored
问题是R似乎不支持raw向量,因为
raw
本身就像字节向量。。。你知道怎么解决这个问题吗

编辑4+5:

我已将目前的建议列为基准:

library(microbenchmark)
x <- sample(c("hello", "my", "world"), 1E6, TRUE)
microbenchmark::microbenchmark(
  sapply_loop  = sapply(x, charToRaw),
  lapply_loop = lapply(x, charToRaw),
  vectorize_loop = { charToRawVec <-Vectorize(charToRaw, "x")
                     charToRawVec(x) },
  split = split(charToRaw(paste(x, collapse = "")), rep(seq_len(length(x)), nchar(x))),
  charToRaw_with_cpp = charToRaw_cpp(x),
  times = 5
)

您可以使用
Vectorize()
完成此任务:

x <- c("hello", "my", "world")
charToRawVec <- Vectorize(FUN = charToRaw, vectorize.args = "x")
charToRawVec(x)

x这是一个使用for
charToRaw
的版本,没有任何错误检查。
Rcpp
中的循环应该尽可能快,尽管我不知道是否有更好的方法来处理内存分配。正如您所看到的,您在
purrr::map
上没有获得统计上显著的性能提升,但它比
sapply
要好

library(Rcpp)

Rcpp::cppFunction('List charToRaw_cpp(CharacterVector x) {
  int n = x.size();
  List l = List(n);

  for (int i = 0; i < n; ++i) {
    int nc = LENGTH(x[i]);
    RawVector ans = RawVector(nc);
    memcpy(RAW(ans), CHAR(x[i]), nc);
    l[i] = ans;
  }
  return l;
}')

# Random vector of 5000 strings of 5000 characters each
x <- unlist(purrr::rerun(5000, stringr::str_c(sample(c(letters, LETTERS), 5000, replace = T), collapse = "")))

microbenchmark::microbenchmark(
  sapply(x, charToRaw),
  purrr::map(x, charToRaw),
  charToRaw_cpp(x)
)
经过1000次迭代,您开始看到效果:

关于业绩的编辑说明: 我想,如果字符串和向量越大,性能的差异就越大。但实际上,到目前为止最大的区别在于50个字符串的50长度向量:


好主意。演出怎么样?
矢量化功能是否只是行上的一个“循环”?那么我就不会期望比使用
sapply
mapply
更好的性能了。
Vectorize
mapply
的包装器,我想。我在“纯文字”中添加了我想要的结果,但我的问题是R似乎不支持原始向量:-(我已经研究了“Vectorize”的源代码,它是“just”一个conveniance包装器,确实在内部使用了
mapply
…一个使用
split
的选项:
split(charToRaw(粘贴(x,collapse=”“)、rep(seq_len(长度(x))、nchar(x)))
但未进行性能测试。好主意!对一个字符使用多字节表示的编码可能会有问题,但仍然是一个好方法!事实上,我无法提供输出的
dput
,因为我不知道如何在向量中“嵌入”原始字节向量:-(是的,列表将是一种良好的结果类型。良好的性能是我的痛点(这就是为什么我要求使用“矢量化”版本的
charToRaw
)@markus我尝试了很多不同的方法,但是
split
这一步总是对性能造成巨大的拖累。我认为将其矢量化并加快其速度的唯一方法是Rcpp。我现在为我的问题添加了一个你答案的基准(优于一切:-)-很抱歉我延迟了回答。顺便说一句,回答得很好(显示了Rcpp的强度,以及如果您了解R堆芯内部构件,它是多么容易;-)
x <- c("hello", "my", "world")
charToRawVec <- Vectorize(FUN = charToRaw, vectorize.args = "x")
charToRawVec(x)
library(Rcpp)

Rcpp::cppFunction('List charToRaw_cpp(CharacterVector x) {
  int n = x.size();
  List l = List(n);

  for (int i = 0; i < n; ++i) {
    int nc = LENGTH(x[i]);
    RawVector ans = RawVector(nc);
    memcpy(RAW(ans), CHAR(x[i]), nc);
    l[i] = ans;
  }
  return l;
}')

# Random vector of 5000 strings of 5000 characters each
x <- unlist(purrr::rerun(5000, stringr::str_c(sample(c(letters, LETTERS), 5000, replace = T), collapse = "")))

microbenchmark::microbenchmark(
  sapply(x, charToRaw),
  purrr::map(x, charToRaw),
  charToRaw_cpp(x)
)
Unit: milliseconds
                    expr       min        lq      mean    median       uq       max neval cld
    sapply(x, charToRaw) 60.337729 69.313684 76.908557 73.232365 78.99251 398.00732   100   b
purrr::map(x, charToRaw)  8.849688  9.201125 17.117435  9.376843 10.09294 292.74068   100  a 
        charToRaw_cpp(x)  5.578212  5.827794  7.998507  6.151864  7.10292  23.81905   100  a
Unit: milliseconds
                    expr      min       lq      mean   median        uq      max neval cld
purrr::map(x, charToRaw) 8.773802 9.191173 13.674963 9.425828 10.602676 302.7293  1000   b
        charToRaw_cpp(x) 5.591585 5.868381  9.370648 6.119673  7.445649 295.1833  1000  a
Unit: microseconds
                       expr    min     lq     mean median      uq     max neval cld
       sapply(x, charToRaw) 66.245 69.045 77.44593 70.288 72.4650 862.110   500   b
   purrr::map(x, charToRaw) 65.313 68.733 75.85236 70.599 72.7765 621.392   500   b
          charToRaw_cpp(x)  4.666  6.221  7.47512  6.844  7.7770  58.159   500  a