快速分类的样品,可更换

F. *_*ivé 6 performance r

基本上,我想sort(sample(n, replace = TRUE))进行n = 1e6,且多次(例如1e4次)。

有什么办法可以更快地在R(cpp)中做到吗?

Ral*_*ner 1

正如 @Frank 在评论中提到的,使用tabulate代替是有意义的sort。一旦使用了它,就可以考虑我的dqrng包提供的更快的采样方法

library(dqrng)
m <- 1e6
bm <- bench::mark(sort(sample.int(m, replace = TRUE)),
                  tabulate(sample.int(m, replace = TRUE)),
                  sort(dqsample.int(m, replace = TRUE)),
                  tabulate(dqsample.int(m, replace = TRUE)),
                  check = FALSE)
bm[, 1:4]
#> # A tibble: 4 x 4
#>   expression                                     min   median `itr/sec`
#>   <bch:expr>                                <bch:tm> <bch:tm>     <dbl>
#> 1 sort(sample.int(m, replace = TRUE))         72.3ms   75.5ms      13.2
#> 2 tabulate(sample.int(m, replace = TRUE))     22.8ms   27.7ms      34.6
#> 3 sort(dqsample.int(m, replace = TRUE))       59.5ms     64ms      15.3
#> 4 tabulate(dqsample.int(m, replace = TRUE))   14.4ms   16.3ms      57.0
Run Code Online (Sandbox Code Playgroud)

由reprex 包(v0.3.0)于 2019-06-27 创建

请注意,我在这台机器上仍在使用 R 3.5。sample.int对于 R 3.6,和之间的差异dqsample.int会更大。另请注意,不再需要 dqrng 的开发版本来获得快速采样方法。

tabulate(dqsample.int(...))人们还可以通过 C++ 使用 dqrng 中的 RNG,但这与我的经验相比并没有太大区别:

#include <Rcpp.h>
// [[Rcpp::depends(dqrng, sitmo)]]
#include <dqrng_generator.h>
#include <convert_seed.h>
#include <R_randgen.h>
// [[Rcpp::plugins(cpp11)]]

// [[Rcpp::export]]
Rcpp::IntegerVector sort_sample(uint32_t n) {
    Rcpp::IntegerVector seed(2, dqrng::R_random_int);
    auto rng = dqrng::generator(dqrng::convert_seed<uint64_t>(seed));
    Rcpp::IntegerVector tab(n);
    for (uint32_t i = 0; i < n; i++) {
        uint32_t k = (*rng)(n);
        tab[k]++;
    }
    return tab;
}
Run Code Online (Sandbox Code Playgroud)