R + C + CUDA = ...

рдХрднреА-рдХрднреА рдЧрдгрдирд╛ рдХреЛ рдЧрддрд┐ рджреЗрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рдХрдИ рдмрд╛рд░ рддреБрд░рдВрдд рд╡рд╛рдВрдЫрдиреАрдп рд╣реИред рдЙрд╕реА рд╕рдордп, рдЖрдкрдХреЛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ, рд▓реЗрдХрд┐рди рдзреАрдорд╛ рдЙрдкрдХрд░рдг рдЫреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдХреБрдЫ рдирд┐рдЪрд▓реЗ-рд╕реНрддрд░ рдФрд░ рддреЗрдЬрд╝ рдХрд╛ рд╕рд╣рд╛рд░рд╛ рд▓реЗрдирд╛ рд╣реЛрдЧрд╛ред C рдХреЗ рдкрд╛рд╕ C / C ++, рдлреЛрд░рдЯреНрд░рд╛рди рдпрд╛ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЬрд╛рд╡рд╛ рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рдЧрддрд┐рд╢реАрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рдЙрдиреНрдирдд рдХреНрд╖рдорддрд╛рдПрдВ рд╣реИрдВред рдЖрджрдд рд╕реЗ рдмрд╛рд╣рд░, рдореИрдВ C / C ++ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВред





рдЖрд░ рдФрд░ рд╕реА



рддреБрд░рдВрдд рдПрдХ рдЖрд░рдХреНрд╖рдг рдХрд░реЗрдВ рдХрд┐ рдореИрдВ рдбреЗрдмрд┐рдпрди рд╡реНрд╣реАрдЬрд╝реА (рд╡рд┐рдВрдбреЛрдЬ рдХреЗ рддрд╣рдд, рд╢рд╛рдпрдж рдХреБрдЫ рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЗ рддрд╣рдд) рдХрд╛рдо рдХрд░рддрд╛ рд╣реВрдВред R рдХреЗ рд▓рд┐рдП C рдореЗрдВ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд▓рд┐рдЦрддреЗ рд╕рдордп, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:



рдЖрдЗрдП рдПрдХ рд╕рд░рд▓ рдХрд╛рд░реНрдп рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ рдЬреЛ рджреЛ рд╡реИрдХреНрдЯрд░ рдХреЗ рдЕрджрд┐рд╢ рдЙрддреНрдкрд╛рдж рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ:







 #include <Rh> void iprod(double *v1, double *v2, int *n, double *s) { double ret = 0; int len = *n; for (int i = 0; i < len; i++) { ret += v1[i] * v2[i]; } *s = ret; }
      
      





рдЕрдЧрд▓рд╛, рдЖрдкрдХреЛ рдПрдХ рдЧрддрд┐рд╢реАрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рдЖрдк рд╕реАрдзреЗ рдЬреАрд╕реАрд╕реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдЖрдк рдЗрд╕ рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рд╡реИрд╕реЗ, рдЖрдкрдХреЛ рдЖрдЙрдЯрдкреБрдЯ рдпрд╛рдж рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛):

 R CMD SHLIB inner_prod.c
      
      





рдЖрдЙрдЯрдкреБрдЯ рдкрд░, рд╣рдореЗрдВ рдЗрдирд░_рдкреНрд░реЛрдб.рд╕реЛ рдлрд╝рд╛рдЗрд▓ рдорд┐рд▓рддреА рд╣реИ, рдЬрд┐рд╕реЗ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо dyn.load()



рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдлрд╝рдВрдХреНрд╢рди рдХреЛ C рдореЗрдВ рд╕реНрд╡рдпрдВ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, .C()



.External()



.C()



(рд╡рд╣рд╛рдБ рднреА рд╣реИ .External()



.Call()



рдФрд░ .External()



, рд▓реЗрдХрд┐рди рдереЛрдбрд╝реА рдЕрд▓рдЧ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рде, рдФрд░ рдХрднреА-рдХрднреА .External()



.Call()



рдФрд░ .External()



рдХреЗ рд╕рдорд░реНрдердХреЛрдВ рдХреЗ рдмреАрдЪ рдЧрд░реНрдо рдмрд╣рд╕ рд╣реЛрддреА рд╣реИред рдореИрдВ рдХреЗрд╡рд▓ рдпрд╣ рдзреНрдпрд╛рди рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдЬрдм .C()



рдорд╛рдзреНрдпрдо рд╕реЗ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реА рдореЗрдВ рдХреЛрдб рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ .C()



рддреЛ рдпрд╣ рдХреНрд▓реАрдирд░ рдФрд░ рдЕрдзрд┐рдХ рдкрдардиреАрдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЖрд░ рдФрд░ рд╕реА рдореЗрдВ рдЪрд░ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкрддреНрд░рд╛рдЪрд╛рд░ рдкрд░ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП .C()



рд▓рд┐рдП рдкреНрд░рд▓реЗрдЦрди .C()



рдлрд╝рдВрдХреНрд╢рди рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ .C()



рд╣реИ)ред рдЖрд░ рдкрд░ рдЖрд╡рд░рдг рд╕рдорд╛рд░реЛрд╣:

 iprod <- function(a, b) { if (!is.loaded('iprod')) { dyn.load("inner_prod.so") } n <- length(a) v <- 0 return(.C("iprod", as.double(a), as.double(b), as.integer(n), as.double(v))[[4]]) }
      
      





рдЕрдм рдЖрдк рдпрд╣ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдордиреЗ рдХреНрдпрд╛ рд╣рд╛рд╕рд┐рд▓ рдХрд┐рдпрд╛ рд╣реИ:

 > n <- 1e7; a <- rnorm(n); b <- rnorm(n); > iprod(a, b) [1] 3482.183
      
      





рдФрд░ рдереЛрдбрд╝рд╛ рдЪреЗрдХ рдХрд░реЗрдВ:

 > sum(a * b) [1] 3482.183
      
      





рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рд╡рд╣ рд╕рд╣реА рд╕реЛрдЪрддрд╛ рд╣реИред



рдЖрд░ рдФрд░ CUDA



рдЙрди рд╕рднреА рд▓рд╛рднреЛрдВ рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЛ рдПрдирд╡реАрдбрд┐рдпрд╛ рдЧреНрд░рд╛рдлрд┐рдХреНрд╕ рдПрдХреНрд╕реЗрд▓реЗрд░реЗрдЯрд░ рдбреЗрдмрд┐рдпрди рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдирд╡реАрдбрд┐рдпрд╛ рдорд╛рд▓рд┐рдХрд╛рдирд╛ рдЪрд╛рд▓рдХ рдФрд░ рдПрдирд╡реАрдбрд┐рдпрд╛ nvidia-cuda-toolkit



рдкреИрдХреЗрдЬ nvidia-cuda-toolkit



ред CUDA рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдЕрд▓рдЧ рд╡рд┐рд╢рд╛рд▓ рд╡рд┐рд╖рдп рдХрд╛ рд╣рдХрджрд╛рд░ рд╣реИ, рдФрд░ рдЪреВрдВрдХрд┐ рдЗрд╕ рд╡рд┐рд╖рдп рдореЗрдВ рдореЗрд░рд╛ рд╕реНрддрд░ "рдиреМрд╕рд┐рдЦрд┐рдпрд╛" рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЕрдкрдиреЗ рдХреБрдЯрд┐рд▓ рдФрд░ рдЕрдкреВрд░реНрдг рдХреЛрдб рд╡рд╛рд▓реЗ рд▓реЛрдЧреЛрдВ рдХреЛ рдирд╣реАрдВ рдбрд░рд╛рдКрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдореИрдиреБрдЕрд▓ рд╕реЗ рдХреБрдЫ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдиреЗ рджреЗрдВред

рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╡реЗрдХреНрдЯрд░ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЛ рддреАрд╕рд░реА рд╢рдХреНрддрд┐ рддрдХ рдЙрдард╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдФрд░ рдкрд░рд┐рдгрд╛рдореА рд╡реЗрдХреНрдЯрд░ рдХреЗ рдпреВрдХреНрд▓рд┐рдбрд┐рдпрди рдорд╛рди рдХреЛ рдЦреЛрдЬрдирд╛ рд╣реЛрдЧрд╛:







GPU рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо Thrust



рд╕рдорд╛рдирд╛рдВрддрд░ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рд╣рдореЗрдВ рдирд┐рдореНрди-рд╕реНрддрд░реАрдп CUDA / C рд╕рдВрдЪрд╛рд▓рди рд╕реЗ рдЕрдореВрд░реНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдбреЗрдЯрд╛ рдХреЛ рд╡реИрдХреНрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХреБрдЫ рдорд╛рдирдХ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рд▓рд╛рдЧреВ рд╣реЛрддреЗ рд╣реИрдВ (рдПрд▓рд┐рдореЗрдВрдЯ рдСрдкрд░реЗрд╢рдВрд╕, рд░рд┐рдбрдХреНрд╢рди, рдкреНрд░реАрдлрд┐рдХреНрд╕-рд╕реЛрдореНрд╕, рд╕реЙрд░реНрдЯрд┐рдВрдЧ)ред

 #include <thrust/transform_reduce.h> #include <thrust/device_vector.h> #include <cmath> // ,     6   GPU (device) template <typename T> struct power{ __device__ T operator()(const T& x) const{ return std::pow(x, 6); } }; extern "C" void nrm(double *v, int *n, double *vnorm) { // ,    GPU,     *v thrust::device_vector<double> dv(v, v + *n); // Reduce- , ..        power //    . *vnorm = std::sqrt( thrust::transform_reduce(dv.begin(), dv.end(), power<double>(), 0.0, thrust::plus<double>()) ); }
      
      





extern "C"



рдХрд░рдирд╛ рдпрд╣рд╛рдВ рдЕрдирд┐рд╡рд╛рд░реНрдп рд╣реИ, рдЕрдиреНрдпрдерд╛ рдЖрд░ рдПрдирдЖрд░рдПрдо () рдлрд╝рдВрдХреНрд╢рди рдирд╣реАрдВ рджреЗрдЦреЗрдЧрд╛ред рдЕрдм рд╣рдо рдХреЛрдб рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП nvcc рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдХрдорд╛рдВрдб R CMD SHLIB...



рдХрд╛ рдЖрдЙрдЯрдкреБрдЯ рдпрд╛рдж рд░рдЦреЗрдВ R CMD SHLIB...



? рдпрд╣рд╛рдБ рдпрд╣ рдереЛрдбрд╝рд╛ рд╕рд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░реЗрдВ рддрд╛рдХрд┐ CUDA / рдереНрд░рд╕реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ R рд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХреЗ:

 nvcc -g -G -O2 -arch sm_30 -I/usr/share/R/include -Xcompiler "-Wall -fpic" -c thr.cu thr.o nvcc -shared -lm thr.o -o thr.so -L/usr/lib/R/lib -lR
      
      





рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рд╣рдореЗрдВ DSO thr.so рдорд┐рд▓рддрд╛ рд╣реИред рдЖрд╡рд░рдг рд╕рдорд╛рд░реЛрд╣ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реИ:

 gpunrm <- function(v) { if (!is.loaded('nrm')) dyn.load("thr.so") n <- length(v) vnorm <- 0 return(.C("nrm", as.double(v), as.integer(n), as.double(vnorm))[[3]]) }
      
      





рдиреАрдЪреЗ рджрд┐рдпрд╛ рдЧрдпрд╛ рдЧреНрд░рд╛рдл рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рд╡реЗрдХреНрдЯрд░ рдХреА рд▓рдВрдмрд╛рдИ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд░рдирдЯрд╛рдЗрдо рдХреИрд╕реЗ рдмрдврд╝рддрд╛ рд╣реИред рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдпрджрд┐ рдЧрдгрдирд╛рдУрдВ рдореЗрдВ рдЬреЛрдбрд╝ / рдШрдЯрд╛рд╡ рдЬреИрд╕реЗ рд╕рд░рд▓ рдСрдкрд░реЗрд╢рди рд╣реЛрддреЗ рд╣реИрдВ, рддреЛ рд╕реАрдкреАрдпреВ рдФрд░ рдЬреАрдкреАрдпреВ рдкрд░ рдЧрдгрдирд╛ рд╕рдордп рдХреЗ рдмреАрдЪ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рдХреЛрдИ рдЕрдВрддрд░ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдмрд╣реБрдд рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ GPU рдореЗрдореЛрд░реА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдУрд╡рд░рд╣реЗрдб рдХреЗ рдХрд╛рд░рдг рдЦреЛ рдЬрд╛рдПрдЧрд╛ред







рдЫрд┐рдкрд╛ рд╣реБрдЖ рдкрд╛рда
 gpu_time <- c() cpu_time <- c() n <- seq.int(1e4, 1e8, length.out=30) for (i in n) { v <- rnorm(i, 1000) gpu_time <- c(gpu_time, system.time({p1 <- gpunrm(v)})[1]) cpu_time <- c(cpu_time, system.time({p2 <- sqrt(sum(v^6))})[1]) }
      
      









рдирд┐рд╖реНрдХрд░реНрд╖



рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдореЗрдЯреНрд░рд┐рд╕реЗрд╕ рдФрд░ рд╡реИрдХреНрдЯрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд░ рдСрдкрд░реЗрд╢рди рдмрд╣реБрдд рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЕрдиреБрдХреВрд▓рд┐рдд рд╣реИрдВ, рдФрд░ рд░реЛрдЬрдорд░реНрд░рд╛ рдХреА рдЬрд┐рдВрджрдЧреА рдореЗрдВ рдПрдХ GPU рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдмрд╣реБрдд рдмрд╛рд░ рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рд▓реЗрдХрд┐рди рдХрднреА-рдХрднреА GPU рдЧрдгрдирд╛ рд╕рдордп рдХреЛ рдХрд╛рдлреА рдХрдо рдХрд░ рд╕рдХрддрд╛ рд╣реИред CRAN рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рддреИрдпрд╛рд░ рдкреИрдХреЗрдЬ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, gputools



) GPU рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рд┐рдд ( рдпрд╣рд╛рдВ рдЖрдк рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдФрд░ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ)ред



рд╕рдВрджрд░реНрдн



1. .рд╕реА рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЯреВ рдЖрд░ рдХрд╛ рдкрд░рд┐рдЪрдп

2. R рдФрд░ Matlab рдореЗрдВ C рдлрдВрдХреНрд╢рдВрд╕ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛

3. R рдХреЗ рд▓рд┐рдП CUDA C рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд▓рд┐рдЦрдирд╛

4. рдЬреЛрд░ :: CUDA рдЯреВрд▓рдХрд┐рдЯ рдкреНрд░рд▓реЗрдЦрди



PS рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдХреЛрдб рдХреЗ рдЯреБрдХрдбрд╝реЗ рдХреЛ рд╕рд╣реА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдареАрдХ рдХрд┐рдпрд╛ред



All Articles