1

下午好,

x[200:300]在使用 Rcpp 时,我一直在尝试使用与 R 中的子集类似的方法。(注意,这不是我要解决的问题,但我需要在我试图用 C++ 编写的函数中对许多范围进行子集化,我发现这是我性能的瓶颈)

然而,尽管我尝试过使用 rcpp 中的方法、使用迭代器或其他东西,但我似乎没有找到一个最低限度“快速”的解决方案。我发现的大多数解决方案都很慢。

并且查看 Rcpp 的参考,我似乎找不到任何东西,我在 StackExchange 中找不到它。

我知道这段代码现在很丑……但我一无所知

// [[Rcpp::export]]
StringVector range_test_( StringVector& x, int i, int j){
    StringVector vect(x.begin()+i, x.begin()+j);
    return vect;
}

然后,它慢了 800 倍。我一直试图x[i:j]在 rcpp 基础中找到与 R 相同的功能,它非常快......但我找不到它。

 tests_range <- rbenchmark::benchmark(
    x[200:3000],
    range_test_(x, 200, 3000),
    order = NULL,
    replications = 80
)[,1:4]

结果给出

                             test replications elapsed relative
1                     x[200:3000]           80   0.001        1
3       range_test_(x, 200, 3000)           80   0.822      822

如果有人知道如何x[i:j]在 Rcpp 中快速访问子集功能或其他东西,我将不胜感激。我似乎无法找到我缺少的工具。

4

1 回答 1

1

问题是迭代器构造函数制作了一个副本。看到这个页面

将迭代器 first 和 last 之间的数据复制到创建的向量

但是,你可以试试这个

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::StringVector in_range(Rcpp::StringVector &x, int i, int j) {
  return x[Rcpp::Range(i - 1, j - 1)]; // zero indexed
}

花费的时间更近了

> set.seed(20597458)
> x <- replicate(1e3, paste0(sample(LETTERS, 5), collapse = ""))
> head(x)
[1] "NHVFQ" "XMEOF" "DABUT" "XKTAZ" "NQXZL" "NPJLM"
> 
> stopifnot(all.equal(in_range(x, 100, 200), x[100:200]))
> 
> library(microbenchmark)
> microbenchmark(in_range(x, 100, 200), x[100:200], times = 1e4)
Unit: nanoseconds
                  expr  min   lq     mean median   uq     max neval
 in_range(x, 100, 200) 1185 1580 3669.780   1581 1976 3263205 10000
            x[100:200]  790  790 1658.571   1185 1186 2331256 10000

请注意,这里有一个关于 susbetting的页面。我在那里找不到相关的例子。

于 2017-10-10T19:55:14.843 回答