Based on Norm Matloff and Drew Schmidt's Rth package (see https://github.com/Rth-org/Rth/). The idea is to use Thrust in a package that uses Rcpp to expose C++ functions to R.
- CUDA 8.0
- One issue in Rcpp needs to be resolved for this package to compile with
nvcc
. In Version0.12.9
of Rcpp, insystem.file("include/Rcpp/vector/proxy.h", package="Rcpp")
, Line 98 must be changed tostring_name_proxy& operator=(string_name_proxy& other){
, i.e. you need to removeconst
. This line needs to be changed before installingRcppThrust
. You can undo the change onceRcppThrust
is installed.
devtools::install_github("jtilly/RcppThrust",
args = "--configure-args=\"--with-backend=CUDA
--with-cuda-home=/usr/local/cuda-8.0/\"")
devtools::install_github("jtilly/RcppThrust")
Use thrust::sort()
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/copy.h>
#include "Rth.h"
#include "Rcpp.h"
// [[Rcpp::export]]
Rcpp::NumericVector mysort(Rcpp::NumericVector x) {
size_t N = x.size();
thrust::device_vector<double> y(N);
thrust::copy(x.begin(), x.end(), y.begin());
thrust::sort(y.begin(), y.end());
thrust::copy(y.begin(), y.end(), x.begin());
return(x);
}
Use user-defined functor
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/copy.h>
#include "Rth.h"
#include "Rcpp.h"
struct simple_negate : public thrust::unary_function<double,double>
{
__host__ __device__
double operator()(double x)
{
return -x;
}
};
// [[Rcpp::export]]
Rcpp::NumericVector myfunctor(Rcpp::NumericVector x) {
size_t N = x.size();
thrust::device_vector<double> y(N);
thrust::copy(x.begin(), x.end(), y.begin());
thrust::sort(y.begin(), y.end());
thrust::transform(y.begin(), y.end(), y.begin(), simple_negate());
thrust::copy(y.begin(), y.end(), x.begin());
return(x);
}
set.seed(1)
x = runif(1e7)
system.time(y <- sort(x))
#> user system elapsed
#> 1.328 0.004 1.332
system.time(z <- mysort(x))
#> user system elapsed
#> 0.036 0.124 0.163
all.equal(y, z)
#> [1] TRUE