title: Building a tiny R package with CUDA and Rcpp
body: <p>I'm working on a <a href="https://github.com/wlandau/rcppcuda" rel="noreferrer">tiny R package</a> that uses CUDA and Rcpp, adapted from the output of <code>Rcpp.package.skeleton()</code>. I will first describe what happens on the master branch for the commit entitled "fixed namespace". The package installs successfully if I forget CUDA (i.e., if I remove the src/Makefile, change src/rcppcuda.cu to src/rcppcuda.cpp, and comment out the code that defines and calls kernels). But as is, the compilation fails.</p>
  
  <p>I also would like to know how to compile with a Makevars or Makevars.in instead of a Makefile, and in general, try to make this as platform independent as is realistic. I've read about Makevars in the <a href="http://cran.r-project.org/doc/manuals/r-release/R-exts.html" rel="noreferrer">R extensions manual</a>, but I still haven't been able to make it work.</p>
  
  <p>Some of you may suggest <a href="http://www.rcuda.net/" rel="noreferrer"><code>rCUDA</code></a>, but what I'm really after here is improving a big package I've already been developing for some time, and I'm not sure that switching is worth starting again from scratch.</p>
  
  <p>Anyway, here's what happens when I do an <code>R CMD build</code> and <code>R CMD INSTALL</code> on <a href="https://github.com/wlandau/rcppcuda" rel="noreferrer">this one</a> (master branch, commit entitled "fixed namespace").</p>
  
  <pre><code>* installing to library ‘/home/landau/.R/library’
  * installing *source* package ‘rcppcuda’ ...
  ** libs
  ** arch - 
  /usr/local/cuda/bin/nvcc -c rcppcuda.cu -o rcppcuda.o --shared -Xcompiler "-fPIC" -gencode arch=compute_20,code=sm_20 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_35,code=sm_35 -I/apps/R-3.2.0/include -I/usr/local/cuda/include 
  rcppcuda.cu:1:18: error: Rcpp.h: No such file or directory
  make: *** [rcppcuda.o] Error 1
  ERROR: compilation failed for package ‘rcppcuda’
  * removing ‘/home/landau/.R/library/rcppcuda’
  </code></pre>
  
  <p>...which is strange, because I do include Rcpp.h, and Rcpp is installed.</p>
  
  <pre><code>$ R
  
  R version 3.2.0 (2015-04-16) -- "Full of Ingredients"
  Copyright (C) 2015 The R Foundation for Statistical Computing
  Platform: x86_64-unknown-linux-gnu (64-bit)
  </code></pre>
  
  <p>...</p>
  
  <pre><code>&gt; library(Rcpp)
  &gt; sessionInfo()
  R version 3.2.0 (2015-04-16)
  Platform: x86_64-unknown-linux-gnu (64-bit)
  Running under: CentOS release 6.6 (Final)
  
  locale:
   [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
   [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
   [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
   [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
   [9] LC_ADDRESS=C               LC_TELEPHONE=C            
  [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
  
  attached base packages:
  [1] stats     graphics  grDevices utils     datasets  methods   base     
  
  other attached packages:
  [1] Rcpp_0.11.6
  &gt; 
  </code></pre>
  
  <p>I'm using CentOS,</p>
  
  <pre><code>$ cat /etc/*-release
  CentOS release 6.6 (Final)
  LSB_VERSION=base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
  CentOS release 6.6 (Final)
  CentOS release 6.6 (Final)
  </code></pre>
  
  <p>CUDA version 6,</p>
  
  <pre><code>$ nvcc --version
  nvcc: NVIDIA (R) Cuda compiler driver
  Copyright (c) 2005-2013 NVIDIA Corporation
  Built on Thu_Mar_13_11:58:58_PDT_2014
  Cuda compilation tools, release 6.0, V6.0.1
  </code></pre>
  
  <p>and I have access to 4 GPUs of the same make and model.</p>
  
  <pre><code>$ /usr/local/cuda/samples/bin/x86_64/linux/release/deviceQuery 
  /usr/local/cuda/samples/bin/x86_64/linux/release/deviceQuery Starting...
  
   CUDA Device Query (Runtime API) version (CUDART static linking)
  
  Detected 4 CUDA Capable device(s)
  
  Device 0: "Tesla M2070"
    CUDA Driver Version / Runtime Version          6.0 / 6.0
    CUDA Capability Major/Minor version number:    2.0
    Total amount of global memory:                 5375 MBytes (5636554752 bytes)
    (14) Multiprocessors, ( 32) CUDA Cores/MP:     448 CUDA Cores
    GPU Clock rate:                                1147 MHz (1.15 GHz)
    Memory Clock rate:                             1566 Mhz
    Memory Bus Width:                              384-bit
    L2 Cache Size:                                 786432 bytes
    Maximum Texture Dimension Size (x,y,z)         1D=(65536), 2D=(65536, 65535), 3D=(2048, 2048, 2048)
    Maximum Layered 1D Texture Size, (num) layers  1D=(16384), 2048 layers
    Maximum Layered 2D Texture Size, (num) layers  2D=(16384, 16384), 2048 layers
    Total amount of constant memory:               65536 bytes
    Total amount of shared memory per block:       49152 bytes
    Total number of registers available per block: 32768
    Warp size:                                     32
    Maximum number of threads per multiprocessor:  1536
    Maximum number of threads per block:           1024
    Max dimension size of a thread block (x,y,z): (1024, 1024, 64)
    Max dimension size of a grid size    (x,y,z): (65535, 65535, 65535)
    Maximum memory pitch:                          2147483647 bytes
    Texture alignment:                             512 bytes
    Concurrent copy and kernel execution:          Yes with 2 copy engine(s)
    Run time limit on kernels:                     No
    Integrated GPU sharing Host Memory:            No
    Support host page-locked memory mapping:       Yes
    Alignment requirement for Surfaces:            Yes
    Device has ECC support:                        Enabled
    Device supports Unified Addressing (UVA):      Yes
    Device PCI Bus ID / PCI location ID:           11 / 0
    Compute Mode:
       &lt; Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) &gt;
  </code></pre>
  
  <p>...</p>
  
  <pre><code>&gt; Peer access from Tesla M2070 (GPU0) -&gt; Tesla M2070 (GPU1) : Yes
  &gt; Peer access from Tesla M2070 (GPU0) -&gt; Tesla M2070 (GPU2) : Yes
  &gt; Peer access from Tesla M2070 (GPU0) -&gt; Tesla M2070 (GPU3) : Yes
  &gt; Peer access from Tesla M2070 (GPU1) -&gt; Tesla M2070 (GPU1) : No
  &gt; Peer access from Tesla M2070 (GPU1) -&gt; Tesla M2070 (GPU2) : Yes
  &gt; Peer access from Tesla M2070 (GPU1) -&gt; Tesla M2070 (GPU3) : Yes
  &gt; Peer access from Tesla M2070 (GPU2) -&gt; Tesla M2070 (GPU1) : Yes
  &gt; Peer access from Tesla M2070 (GPU2) -&gt; Tesla M2070 (GPU2) : No
  &gt; Peer access from Tesla M2070 (GPU2) -&gt; Tesla M2070 (GPU3) : Yes
  &gt; Peer access from Tesla M2070 (GPU1) -&gt; Tesla M2070 (GPU0) : Yes
  &gt; Peer access from Tesla M2070 (GPU1) -&gt; Tesla M2070 (GPU1) : No
  &gt; Peer access from Tesla M2070 (GPU1) -&gt; Tesla M2070 (GPU2) : Yes
  &gt; Peer access from Tesla M2070 (GPU2) -&gt; Tesla M2070 (GPU0) : Yes
  &gt; Peer access from Tesla M2070 (GPU2) -&gt; Tesla M2070 (GPU1) : Yes
  &gt; Peer access from Tesla M2070 (GPU2) -&gt; Tesla M2070 (GPU2) : No
  &gt; Peer access from Tesla M2070 (GPU3) -&gt; Tesla M2070 (GPU0) : Yes
  &gt; Peer access from Tesla M2070 (GPU3) -&gt; Tesla M2070 (GPU1) : Yes
  &gt; Peer access from Tesla M2070 (GPU3) -&gt; Tesla M2070 (GPU2) : Yes
  
  deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 6.0, CUDA Runtime Version = 6.0, NumDevs = 4, Device0 = Tesla M2070, Device1 = Tesla M2070, Device2 = Tesla M2070, Device3 = Tesla M2070
  Result = PASS
  </code></pre>
  
  <hr>
  
  <p><strong>Edit: it compiles for any commit after "fixed namespace" on either branch, but there are still problems with combining Rcpp and CUDA</strong></p>
  
  <p>To make the package compile, it turns out that I just needed to separate my C++ and CUDA code into separate <code>*.cpp</code> and <code>*.cu</code> files. However, when I try the "compiling cpp and cu separately" commit on the master branch, I get</p>
  
  <pre><code>&gt; library(rcppcuda)
  &gt; hello()
  An object of class "MyClass"
  Slot "x":
   [1]  1  2  3  4  5  6  7  8  9 10
  
  Slot "y":
   [1]  1  2  3  4  5  6  7  8  9 10
  
  Error in .Call("someCPPcode", r) : 
    "someCPPcode" not resolved from current namespace (rcppcuda)
  &gt; 
  </code></pre>
  
  <p>The error goes away in the <code>withoutCUDA</code> branch in the commit entitled "adding branch withoutCUDA".</p>
  
  <pre><code>&gt; library(rcppcuda)
  &gt; hello()
  An object of class "MyClass"
  Slot "x":
   [1]  1  2  3  4  5  6  7  8  9 10
  
  Slot "y":
   [1]  1  2  3  4  5  6  7  8  9 10
  
  [1] "Object changed."
  An object of class "MyClass"
  Slot "x":
   [1] 500   2   3   4   5   6   7   8   9  10
  
  Slot "y":
   [1]    1 1000    3    4    5    6    7    8    9   10
  
  &gt; 
  </code></pre>
  
  <p>The only differences between the "compiling cpp and cu separately" commit on <code>master</code> and the "adding branch withoutCUDA" commit on <code>withoutCUDA</code> are</p>
  
  <ul>
  <li>The Makefile and someCUDAcode.cu are gone from <code>withoutCUDA</code>.</li>
  <li>In <code>withoutCUDA</code>, all references to <code>someCUDAcode()</code> are gone from someCPPcode.cpp.</li>
  </ul>
  
  <p>Also, it would still be convenient be able to use CUDA and Rcpp in the same <code>*.cu</code> file. I would really like to know how to fix the "fixed namespace" commit on the master branch.</p>