RGLab / Rtsne.multicore

R wrapper for Multicore t-SNE
Other
29 stars 3 forks source link

Cannot install on Mac OSX 10.11.6 (15G1217) #5

Closed jolespin closed 7 years ago

jolespin commented 7 years ago
> devtools::install_github("RGLab/Rtsne.multicore")
Downloading GitHub repo RGLab/Rtsne.multicore@master
from URL https://api.github.com/repos/RGLab/Rtsne.multicore/zipball/master
Installing Rtsne.multicore
'/Users/jespinoz/anaconda/lib/R/bin/R' --no-site-file --no-environ --no-save  \
  --no-restore --quiet CMD INSTALL  \
  '/private/var/folders/6z/5vbtz_gmkr76ftgc3149dvtr0003c0/T/RtmpCDQkG7/devtoolsd9a499115dc/RGLab-Rtsne.multicore-6789e40'  \
  --library='/Users/jespinoz/anaconda/lib/R/library' --install-tests

* installing *source* package ‘Rtsne.multicore’ ...
** libs
clang++ -I/Users/jespinoz/anaconda/lib/R/include -DNDEBUG -DROUT -fopenmp -I/Users/jespinoz/anaconda/include -I"/Users/jespinoz/anaconda/lib/R/library/Rcpp/include"   -fPIC  -I/Users/jespinoz/anaconda/include  -c RcppExports.cpp -o RcppExports.o
clang: error: unsupported option '-fopenmp'
make: *** [RcppExports.o] Error 1
ERROR: compilation failed for package ‘Rtsne.multicore’
* removing ‘/Users/jespinoz/anaconda/lib/R/library/Rtsne.multicore’
Installation failed: Command failed (1)
jolespin commented 7 years ago

This is after installing the newest version of Rcpp (Rcpp_0.12.11)

mikejiang commented 7 years ago

You may need to install clang-omp or switch to gcc

jolespin commented 7 years ago

Do you have any suggestions on how to do that?

claczny commented 7 years ago

I tried to install it on Mac OS X (10.11.6 (15G1004)) and quickly ran into this error too. After a quick search, I found https://asieira.github.io/using-openmp-with-r-packages-in-os-x.html which allowed to continue with the compilation. N.B. I installed GCC via macports. This is what I added to my ~/.R/Makevars

## https://asieira.github.io/using-openmp-with-r-packages-in-os-x.html
CC=/opt/local/bin/gcc-mp-5
CXX=/opt/local/bin/g++-mp-5
CXX1X=/opt/local/bin/g++-mp-5
SHLIB_CXXLD=/opt/local/bin/g++-mp-5
FC=/opt/local/bin/gfortran-mp-5
F77=/opt/local/bin/gfortran-mp-5
MAKE=make -j2

SHLIB_OPENMP_CFLAGS=-fopenmp
SHLIB_OPENMP_CXXFLAGS=-fopenmp
SHLIB_OPENMP_FCFLAGS=-fopenmp
SHLIB_OPENMP_FFLAGS=-fopenmp

However, now it fails at a later step:

/opt/local/bin/g++-mp-5 -std=c++11 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/Library/Frameworks/R.framework/Resources/lib -L/usr/local/lib -o Rtsne.multicore.so RcppExports.o Rtsne.o quadtree.o tsne.o -fopenmp -L/Library/Frameworks/R.framework/Resources/lib -lRlapack -L/Library/Frameworks/R.framework/Resources/lib -lRblas -L/usr/local/lib/gcc/x86_64-apple-darwin13.0.0/4.8.2 -lgfortran -lquadmath -lm -F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -Wl,CoreFoundation
installing to /Library/Frameworks/R.framework/Versions/3.2/Resources/library/Rtsne.multicore/libs
** R
** inst
** tests
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
Error in dyn.load(file, DLLpath = DLLpath, ...) : 
  unable to load shared object '/Library/Frameworks/R.framework/Versions/3.2/Resources/library/Rtsne.multicore/libs/Rtsne.multicore.so':
  dlopen(/Library/Frameworks/R.framework/Versions/3.2/Resources/library/Rtsne.multicore/libs/Rtsne.multicore.so, 6): Symbol not found: _GOMP_parallel
  Referenced from: /Library/Frameworks/R.framework/Versions/3.2/Resources/library/Rtsne.multicore/libs/Rtsne.multicore.so
  Expected in: flat namespace
 in /Library/Frameworks/R.framework/Versions/3.2/Resources/library/Rtsne.multicore/libs/Rtsne.multicore.so
Error: loading failed
Execution halted
ERROR: loading failed
* removing ‘/Library/Frameworks/R.framework/Versions/3.2/Resources/library/Rtsne.multicore’
Installation failed: Command failed (1)

And I am stuck.

Your ideas are greatly appreciated!

Best,

Cedric

gfinak commented 7 years ago

The error suggests that libgomp is not found during dynamic loading.

You’ll need to figure out where that library lives (likely somewhere where the libraries for g++-mp-5 are located), and then make sure your DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH point to that location in the path list.

That should help…

claczny commented 7 years ago

@gfinak Thx for the quick reply. I tried this out but the error remained.

tl;dr I needed to specify LDFLAGS = -L/opt/local/lib/gcc5/ in my ~/.R/Makevars; my full ~/.R/Makevars is provided below.

Now to my little journey for those interested: Motivated by @gfinak s suggestion, I specified various environment variables (e.g., Sys.setenv(R_DYLD_FALLBACK_LIBRARY_PATH=paste("/opt/local/lib/gcc5", Sys.getenv("R_DYLD_FALLBACK_LIBRARY_PATH"),sep=":")) in the hopes that one would be the correct one (https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#OpenMP-Support):

DYLD_FALLBACK_LIBRARY_PATH
                        /opt/local/lib/gcc5:/Library/Frameworks/R.framework/Resources/lib:/Library/Java/JavaVirtualMachines/jdk1.8.0_66.jdk/Contents/Home/jre/lib/server
DYLD_LIBRARY_PATH       /opt/local/lib/gcc5:
LD_LIBRARY_PATH         /opt/local/lib/gcc5:
R_DYLD_FALLBACK_LIBRARY_PATH
                        /opt/local/lib/gcc5:
R_DYLD_LIBRARY_PATH     /opt/local/lib/gcc5:

but none of them alone worked; I kept getting the linker error.

Strangely, when I had only PKG_LIBS= -L/opt/local/lib/gcc5/ at some point during testing, i.e., lacking the -lgomp, I got an error that _GOMP_barrier could not be found.

This made me wonder why it seems to find some symbols but not others. Thus, I wanted to have a look at the Rtsne.multicore.so file myself. However, that file got removed upon an error.

So I had a look at R CMD INSTALL --help and stumbled over the --no-clean-on-error flag, which I then specified: devtools::install_github("RGLab/Rtsne.multicore", args="--no-clean-on-error"). Subsequently, I had a look at the respective file via otool -L /Library/Frameworks/R.framework/Versions/3.2/Resources/library/Rtsne.multicore/libs/Rtsne.multicore.so which returned:

/Library/Frameworks/R.framework/Versions/3.2/Resources/library/Rtsne.multicore/libs/Rtsne.multicore.so:
    Rtsne.multicore.so (compatibility version 0.0.0, current version 0.0.0)
    /usr/local/lib/libgomp.1.dylib (compatibility version 2.0.0, current version 2.0.0)
    /Library/Frameworks/R.framework/Versions/3.2/Resources/lib/libR.dylib (compatibility version 3.2.0, current version 3.2.3)
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1258.1.0)
    /opt/local/lib/libgcc/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.22.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
    /usr/local/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)

Heck, why is it linking against libgomp.1.dylib in /usr/local/lib/? It should be /opt/local/lib/gcc5.

After another search, I found https://cran.r-project.org/doc/manuals/r-devel/R-admin.html#Compilation-flags, which motivated me to add LDFLAGS = -L/opt/local/lib/gcc5/ to my ~/.R/Makevars and, voila presto, it worked!

** R
** inst
** tests
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (Rtsne.multicore)

So my full ~/.R/Makevars looks as follows and may contain extraneous stuff:

## https://asieira.github.io/using-openmp-with-r-packages-in-os-x.html
CC=/opt/local/bin/gcc-mp-5
CXX=/opt/local/bin/g++-mp-5
CXX1X=/opt/local/bin/g++-mp-5
SHLIB_CXXLD=/opt/local/bin/g++-mp-5
FC=/opt/local/bin/gfortran-mp-5
F77=/opt/local/bin/gfortran-mp-5
MAKE=make -j2

SHLIB_OPENMP_CFLAGS=-fopenmp
SHLIB_OPENMP_CXXFLAGS=-fopenmp
SHLIB_OPENMP_FCFLAGS=-fopenmp
SHLIB_OPENMP_FFLAGS=-fopenmp

## -- compiling for OpenMP -> https://stackoverflow.com/a/5008957/271775
PKG_CXXFLAGS=-fopenmp
## -- linking for OpenMP
## PKG_LIBS= -fopenmp -lgomp
PKG_LIBS= -L/opt/local/lib/gcc5/ -lgomp `$(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()"`
LDFLAGS = -L/opt/local/lib/gcc5/

R_OPENMP_CFLAGS = -fopenmp
R_OPENMP_FFLAGS = -fopenmp

Hope this helps other Mac OS X users to install this package.

gfinak commented 7 years ago

Thanks for documenting your process here. Perhaps I'll add it to the readme if that's alright.

claczny commented 7 years ago

An independent verification of this process would be great :) Other than that, please feel free to include the info if it helps!

claczny commented 7 years ago

Minor note, just for the record, my first name ends with a "c", not a "k" ;)

claczny commented 6 years ago

UPDATE:

I created a fresh installation on a new Mac Book Pro (macOS 10.13.2 (17C88)) with a local MacPorts (version 2.4.2) installation, i.e., I installed it in my $HOME (for the record: time ./configure --prefix=${HOME}/.macports --with-install-user=${USER} && make && make install). I installed CLANG-4.0 (and GCC-7) via MacPorts, so I changed the $(HOME)/.R/Makevars (R-3.4.3) file accordingly. Interestingly, although I do not (yet) know why exactly, this greatly simplified the content of that file:

# Set the path according to local MacPorts installation
MACPORTS_DIR=/Users/cedric.laczny/.macports
MY_CXX = $(MACPORTS_DIR)/bin/clang++-mp-4.0
CC = $(MACPORTS_DIR)/bin/clang-mp-4.0
CXX = $(MY_CXX)
CXX98 = $(MY_CXX)
CXX11 = $(MY_CXX)
CXX14 = $(MY_CXX)
CXX17 = $(MY_CXX)
PKG_LIBS = -L$(MACPORTS_DIR)/lib/libgcc `$(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()”`

N.B. The extra variables (CXX98, CXX1, CXX14 and CXX17) are apparently needed, s. https://stackoverflow.com/a/43599233/271775 and http://gallery.rcpp.org/articles/rcpp-and-c++11-c++14-c++17/).

The use of MY_CXX is due to simplicity reasons. Using, e.g., $(CXX) instead, lead to (apparently) circular “dependencies/resolution” of the variable and R complained.

I then tested whether, indeed, multiple cores would be used according to the example given in the Rtsne.multicore README and

microbenchmark(tsne_out <- Rtsne.multicore(mat, num_threads = 1), times = 150)
microbenchmark(tsne_out <- Rtsne.multicore(mat, num_threads = 2), times = 150)
microbenchmark(tsne_out <- Rtsne.multicore(mat, num_threads = 3), times = 150)
microbenchmark(tsne_out <- Rtsne.multicore(mat, num_threads = 4), times = 150)

giving me approx. 25%, 50%, 75%, and 100% CPU utilizations, respectively.

P.S. I chose a local MacPorts installation as I try to reduce the clutter throughout my system this time ;)