RcppEigen and Vectorization - r

In Eigen FAQ it states that you need to enable vectorization in the compiler.
I am trying to develop an R package using RcppEigen. I would like it if the user would have the best performance without having to manually compile the package with specified flags.
What is best practice for an R package looking to enable vectorization in the Eigen library?

Do exactly what the FAQ says and set the compiler flags. You may have to turn those on from a script configure after you test what the current compiler supports -- and CRAN may still tell you that the flags are not portable.
Also, just to fix terms here, there is no "library" here in our: RcppEigen only uses headers from Eigen which is designed as a templated header-only package.

I'm a beginner too and many hours trying to understand Rcpp may be relevant to you #jds. I wanted to enable vectorisation on my Dell Precision M2800 with AVX architecture so I added the -mavx2 flag to my configure file using the following chunk thrice:
CXXFLAGS= -O3 -std=c++11 -Wall -mavx2
This code change sped up my code (a series of double-nested for loops) from 4.1s to 1.4s!
Find out how to amend the compiler flags that get used by sourceCpp by building a skeleton package using configure and clean files to create your Makevars file as beautifully demonstrated by #nrussell in How to change and set Rcpp compile arguments

Related

How does a typical Rcpp edit-compile-test cycle look like?

I can only find information on how to install a ready-made R extension package, but it is nowhere mentioned which commands a developer of an extension package has to use during daily development. I am using Rcpp and I am on Windows.
If this were a typical C++ project, it would go like this:
edit
make # oops, typo
edit # fix typo
make # oops, forgot an #include
edit
make # good; updates header dependencies for subsequent 'make' automatically
./fooreader # test it
make install # only now I'm ready
Which commands do I need for daily development of an Rcpp package project?
I've allocated a skeleton project using these commands from the R command line:
library(Rcpp)
Rcpp.package.skeleton("FooReader", example_code=FALSE,
author="My Name", email="my.email#example.com")
This allocated 3 files:
DESCRIPTION
NAMESPACE
man/FooReader-package.Rd
Now I dropped source code into
src/readfoo.cpp
with these contents:
#include <Rcpp.h>
#error here
I know I can run this from the R command line:
Rcpp::sourceCpp("D:/Projects/FooReader/src/readfoo.cpp")
(this does run the compiler and indicates the #error).
But I want to develop a package ultimately.
There is no universal answer for everybody, I guess.
For some people, RStudio is everything, and with some reason. One can use the package creation facility to create an Rcpp package, then edit and just hit the buttons (or keyboard shortcuts) to compile and re-load and test.
I also work a lot on a shell, so I do a fair amount of editing in Emacs/ESS along with R CMD INSTALL (where thanks to ccache recompilation of unchanged code is immediate) with command-line use via r of the littler package -- this allows me to write compact expressions loading the new package and evaluating: r -lnewpackage -esomeFunc(somearg) to test newpackage::someFunc() with somearg.
You can also launch the build and test from Emacs. As I said, it all depends.
Both those answers are for package, where I do real work. When I just test something in a single file, I do that in one Emacs buffer and sourceCpp() in an R session in another buffer of the same Emacs. Or sometimes I edit in Emacs and run sourceCpp() in RStudio.
There is no one answer. Find what works for you.
Also, the first part of your question describes the initial setup of a package. That is not part of the edit/compile/link/test cycle as it is a one off. And for that too do we have different approaches many of which have been discussed here.
Edit: The other main misunderstanding of your question is that once you have package you generally do not use sourceCpp() anymore.
In order to test an R package, it has to be installed into a (temporary) library such that it can be attached to a running R process. So you will typically need:
R CMD build . to build package_version.tar.gz
R CMD check <package_version.tar.gz> to test your package, including tests placed into the testsfolder
R CMD INSTALL <package_version.tar.gz> to install it into a library
After that you can attach the package and test it. Quite often I try to use a more TTD approach, which means I do not have to INSTALL the package. Running the unit tests (e.g. via R CMD check) is enough.
All that is independent of Rcpp. For a package using Rcpp you need to call Rcpp::compileAttributes() before these steps, e.g. with Rscript -e 'Rcpp::compileAttributes()'.
If you use RStudio for package development, it offers a lot of automation via the devtools package. I still find it useful to know what has to go on under the hood and it is by no means required.

Why can R be linked to a shared BLAS later even if it was built with `--with-blas = lblas`?

The BLAS section in R installation and administration manual says that when R is built from source, with configuration parameter --without-blas, it will build Netlib's reference BLAS into a standalone shared library at R_HOME/lib/libRblas.so, along side the standard R shared library R_HOME/lib/libR.so. This makes it easier for user to switch and benchmark different tuned BLAS in R environment. The guide suggests that researcher might use symbolic link to libRblas.so to achieve this, and this article gives more details on this.
On contrary, when simply installing a pre-compiled binary version of R, either from R CRAN's mirrors or Ubuntu's repository (for linux user like me), in theory it should be more difficult to switch between different BLAS without rebuilding R, because a pre-compiled R version is configured with --with-blas = (some blas library). We can easily check this, either by reading configuration file at R_HOME/etc/Makeconf, or check the result of R CMD config BLAS_LIBS. For example, on my machine it returns -lblas, so it is linked to reference BLAS at build time. As a result, there is no R_HOME/lib/libRblas.so, only R_HOME/lib/libR.so.
However, this R-blog says that it is possible to switch between difference BLAS, even if R is not installed from source. The author tried the ATLAS and OpenBLAS from ubuntu's repository, and then use update-alternatives --config to work around. It is also possible to configure and install tuned BLAS from source, add them to "alternatives" through update-alternatives --install, and later switch between them in the same way. The BLAS library (a symbolic link) in this case will be found at /usr/lib/libblas.so.3, which is under both ubuntu and R's LD_LIBRARY_PATH. I have tested and this does work! But I am very surprised at how R achieves this. As I said, R should have been tied to the BLAS library configured at building time, i.e., I would expect all BLAS routines integrated into R_HOME/lib/libR.so. So why is it still possible to change BLAS via /usr/lib/libblas.so.3?
Thanks if someone can please explain this.

Detect whether the compiler has full C++11 support from Rcpp

I am building a package using Rcpp and RcppArmadillo, and when I install it on one of my machines I get the following compiler warnings from functions which use RcppArmadillo:
WARNING: your C++ compiler is in C++11 mode, but it has incomplete
support for C++11 features; if something breaks, you get to keep all
the pieces
As far as I can tell, this doesn't break any of my code, however it would be nice to turn off these warnings if possible.
Based on another question I know I can disable C++11 support for Armadillo by adding the following macro before I include the RcppArmadillo header file:
#define ARMA_DONT_USE_CXX11
Which is just a shorthand for:
#if defined(ARMA_DONT_USE_CXX11)
#undef ARMA_USE_CXX11
#undef ARMA_USE_CXX11_RNG
#endif
What I'd like to be able to do is detect whether the compiler has full support for C++11 extensions or not, and #undef the appropriate macros only if the machines compiler doesn't support full C++11 extensions.
According to the R extensions manual, this should be stored in CXX1XSTD, so I want to do something like:
#if CXX1XSTD == "-std=c++0x"
#undef ARMA_USE_CXX11
#undef ARMA_USE_CXX11_RNG
#endif
However CXX1XSTD isn't a predefined macro in Rcpp or C++, so I that doesn't work.
Briefly:
The first warning is from Armadillo. Conrad works hard to keep his code compliant; he chose to put this warning in. You did not say which compiler version you used so I can't comment further.
The rest of your post is a little confused. There are actual test macros for compilers and versions -- a well known source is this one at sf.net -- and we try out best to reflect that in our sources.
In short, g++ 4.8 or later (as on Linux) and clang 3.4 or 3.5 (as on Linux and OS X) are good enough.
Windows and its g++ 4.6.* has issues. That latter one is the compiler we are given by Rtools and there is little we can do.
CXX1XSTD is defined by R 3.1.0 or later. R tests the compiler during its compile / build cycle and remember, so when as you for a C++11 etc compliant compiler R knows whether to give you c++0x or c++11. In essence, you are thinking here that you know better; I think you may be wrong in that belief. But hey, if there is something we can do better than we currently do in the Rcpp / RcppArmadillo headers then let us know.
I didn't see where you said why you turned C++11 on. Are you actually using C++11 or later features? Because if you don't then the whole issue is moot. But if you do then you need to be careful. Many R installations will have old compilers (Windows, older RHEL, ...).
I suspect you'd get overall better respones if you posted on rcpp-devel.

fast install package during development with multiarch

I'm working on a package "xyz" that uses Rcpp with several cpp files.
When I'm only updating the R code, I would like to run R CMD INSTALL xyz on the package directory without having to recompile all the shared libraries that haven't changed. That works fine if I specify the --no-multiarch flag: the source directory src gets populated the first time with the compiled objects, and if the sources don't change they are re-used the next time. With multiarch on, however, R decides to make two copies of src, src-i386 and src-x86_64. It seems to confuse R CMD INSTALL which always re-runs all the compilation. Is there any workaround?
(I'm aware that there are alternative ways, e.g. devtools::load_all, but I'd rather stick to R CM INSTALL if possible).
The platform is MacOS 10.7, and I have the latest version of R.
I have a partial answer for you. One really easy for speed-up is provided by using ccache which you can enable for all R compilation (e.g. via R CMD whatever thereby also getting inline, attributes, RStudio use, ...) globally through .R/Makevars:
edd#max:~$ tail -10 .R/Makevars
VER=4.6
CC=ccache gcc-$(VER)
CXX=ccache g++-$(VER)
SHLIB_CXXLD=g++-$(VER)
FC=ccache gfortran
F77=ccache gfortran
MAKE=make -j8
edd#max:~$
It takes care of all caching of compilation units.
Now, that does not "explicitly" address the --no-multiarch aspect which I don;t play much with that as we are still mostly 'single arch' on Linux. This will change, eventually, but hasn't yet. Yet I suspect but by letting the compiler decide the caching you too will get the net effect.
Other aspects can be controlled too, eg ~/.R/check.Renviron can be used to turn certain tests on or off. I tend to keep'em all on -- better to waste a few seconds here than to get a nastygram from Vienna.

Setting up "configure" for openMP in R

I have an R package which is easily sped up by using OpenMP. If your compiler supports it then you get the win, if it doesn't then the pragmas are ignored and you get one core.
My problem is how to get the package build system to use the right compiler options and libraries. Currently I have:
PKG_CPPFLAGS=-fopenmp
PKG_LIBS=-fopenmp
hardcoded into src/Makevars on my machine, and this builds it with OpenMP support. But it produces a warning about non-standard compiler flags on check, and will probably fail hard on a machine with no openMP capabilities.
The solution seems to be to use configure and autoconf. There's some information around here:
http://cran.r-project.org/doc/manuals/R-exts.html#Using-Makevars
including a complex example to compile in odbc functionality. But I can't see how to begin tweaking that to check for openmp and libgomp.
None of the R packages I've looked at that talk about using openMP seem to have this set up either.
So does anyone have a walkthrough for setting up an R package with OpenMP?
[EDIT]
I may have cracked this now. I have a configure.ac script and a Makevars.in with #FOO# substitutions for the compiler options. But now I'm not sure of the workflow. Is it:
Run "autoconf configure.in > configure; chmod 755 configure" if I change the configure.in file.
Do a package build.
On package install, the system runs ./configure for me and creates Makevars from Makevars.in
But just to be clear, "autoconf configure.in > configure" doesn't run on package install - its purely a developer process to create the configure script that is distributed - amirite?
Methinks you have the library option wrong, please try
## -- compiling for OpenMP
PKG_CXXFLAGS=-fopenmp
##
## -- linking for OpenMP
PKG_LIBS= -fopenmp -lgomp
In other words, -lgomp gets you the OpenMP library linked. And I presume you know that this library is not part of the popular Rtools kit for Windows. On a modern Linux you should be fine.
In an unrelease testpackage I have here I also add the following to PKG_LIBS, but that is mostly due to my use of Rcpp:
$(shell $(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()") \
$(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
Lastly, I think the autoconf business is not really needed unless you feel you need to test for OpenMP via configure.
Edit: SpacedMan is correct. Per the beginning of the libgomp-4.4 manual:
1 Enabling OpenMP
To activate the OpenMP extensions for
C/C++ and Fortran, the compile-time
flag `-fopenmp' must be specified.
This enables the OpenMP directive
[...] The flag also
arranges for automatic linking of the
OpenMP runtime library.
So I stand corrected. Seems that it doesn't hurt to manually add what would get added anyway, just for clarity...
Just addressing your question regarding the usage of autoconf--no, you do not want to run autoconf with any arguments, nor should you redirect its output. You are correct that running autoconf to build the configure script is something that the package maintainer does, and the resulting configure script is distributed. Normally, to generate the configure script from configure.ac (older packages use the name configure.in, but that name has been discouraged for several years), the developer simply runs autoconf with no arguments. Before running autoconf, it is necessary to run aclocal, autoheader, libtoolize, etc... There is also a tool (autoreconf) which simplifies the process and invokes all the required programs in the correct order. It is now more typical to run autoreconf instead of autoconf.

Resources