s-u / OpenCL

Interface allowing R to use OpenCL
Other
15 stars 10 forks source link

Installation Documentation Incomplete/Unclear #17

Closed aerickso closed 1 year ago

aerickso commented 1 year ago

Thank you for writing OpenCL!

I'm a primary R user, and I would like to try GPU Parallelization for matrix calculations using an R front end with OpenCL. I have a Windows 11 PC, with a NVIDIA RTX 2070 Super GPU. I've performed steps 0-3 from here, eg, installation of updated drivers, CUDA.

Unfortunately, the documentation 1 cleanly install dependencies and build OpenCL for use with R is not clear. I've also read other flagged issues.

I've now spent a good 5-6 hours of trial and error & reading other online sources, and I can't seem to "crack it". I'm confident if the paths/dependency issues are solved, that I could get to writing code!

Can you help fix my problem? I can't wait to try OpenCL in R. Thanks for your help in advance!

Sys.setenv(OPENCL_INC = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/include") Sys.setenv(OPENCL_LIB32 = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/lib/Win32") Sys.setenv(OPENCL_LIB64 = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/lib/x64")

Sys.setenv(OCLINC = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/include") Sys.setenv(OCL32LIB = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/lib/Win32") Sys.setenv(OCL64LIB = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/lib/x64")

Sys.setenv(OCL = "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/include") dyn.load("C:/Windows/System32/OpenCL.dll", FALSE, TRUE) install.packages("OpenCL") Installing package into ‘C:/Users/erick/AppData/Local/R/win-library/4.2’ (as ‘lib’ is unspecified) Package which is only available in source form, and may need compilation of C/C++/Fortran: ‘OpenCL’ installing the source package ‘OpenCL’

trying URL 'https://cran.rstudio.com/src/contrib/OpenCL_0.2-2.tar.gz' Content type 'application/x-gzip' length 20881 bytes (20 KB) downloaded 20 KB

NOTE: make sure the run-time DLLs are on PATH!

** libs Warning: this package has a non-empty 'configure.win' file, so building only the main architecture

gcc -I"C:/PROGRA~1/R/R-42~1.1/include" -DNDEBUG 'C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/include' -I"C:/rtools42/x86_64-w64-mingw32.static.posix/include" -O2 -Wall -std=gnu99 -mfpmath=sse -msse2 -mstackrealign -c buffer.c -o buffer.o In file included from buffer.c:2: ocl.h:7:10: fatal error: CL/opencl.h: No such file or directory 7 | #include <CL/opencl.h> | ^~~~~ compilation terminated. make: *** [C:/PROGRA~1/R/R-42~1.1/etc/x64/Makeconf:253: buffer.o] Error 1 ERROR: compilation failed for package 'OpenCL'

The downloaded source packages are in ‘C:\Users\erick\AppData\Local\Temp\Rtmp6tR0ZX\downloaded_packages’`

aaronpuchert commented 1 year ago

You'll need to append -I (or better -isystem) in front of OCLINC, so

Sys.setenv(OCLINC = "-isystem C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/include")

Not sure if escaping is needed for the spaces, but you should get an error for that. (If not, try adding -v.) That turns the following argument into an include directory instead of a positional argument, which the compiler ignores (it can't compile directories).

@s-u, is it intentional that users have to append the flag? In configure.win we do

if test -z "$OCLINC"; then
   OCLINC="-I$OCL/include"
   echo OCLINC not set, assuming $OCLINC
fi

but perhaps we should do something like

if test -z "$OCLINC"; then
   OCLINC="$OCL/include"
   echo OCLINC not set, assuming $OCLINC
fi
# ...
PKG_CPPFLAGS="-isystem $OCLINC"

instead? See also the similar discussion at the end of #16.

s-u commented 1 year ago

Looking at the above, all that should be needed is just

Sys.setenv(OCL="C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1")
dyn.load("C:/Windows/System32/OpenCL.dll", FALSE, TRUE)

Everything else is just noise that doesn't really get used or is actually set automatically. As usual, setting manual overrides (like complier and linker flags) if you are not en expert is not recommended.

If the defaults are not working for some reason, that would be good to know, but it's not clear from the report that the documented way (it does say explicitly: "When compiling OpenCL for Windows, you have to set the OCL environment variable to the root of the OpenCL SDK.") didn't work.

s-u commented 1 year ago

@aaronpuchert Why would you use -isystem? It is not a system header so you don't want it to be moved down to the system search fall-back priority, so -I seems most appropriate to me. Both the OCLINC and OCL*LIB variables are compiler flags (as is customary), so it would not work otherwise. I will make it more explicit in the message. As I said above, It think people are overcomplicating things that are designed to be simple (mostly by following bad advice from the Internet).

aaronpuchert commented 1 year ago

As long as you don't have another directory with -I that also has OpenCL headers, priority shouldn't be an issue. And if you do, you need to be careful with order.

Everything that you have no control over (i.e. it's not your code, it's not writable by you) is a system header. (So it's not just the standard library, note that on Linux /usr/include is a system include directory, which can contain all kinds of libraries that you have installed.) Apart from the priority, marking an include directory as system include directory suppresses warnings. Because you cannot fix those warnings, if the files are provided by an external vendor and not part of your own code.

aaronpuchert commented 1 year ago

Also, since OpenCL is tied into your graphics driver, it is arguably very much a system library.

s-u commented 1 year ago

The above makes no sense - the point of the variable is to find the correct headers, so placing the with -isystem does exactly the opposite - makes sure they will not be used - which defeats its very purpose. The whole point is to make sure that the version specified by the user is used, not some random header on the search path. Anyway, this works exactly as intended and I have updated the documentation to be more explicit about it.

aaronpuchert commented 1 year ago

Why would they not be used? If you're worried that someone might smuggle another system include directory onto the command line, you might as well be worried about someone smuggling another -I in that breaks things. (Both are scanned left-to-right, and both precede builtin directories.)

I wouldn't use it in our script, because the packaging guidelines don't want anything GNU to be used, but I would recommend it in general if GCC/Clang is known to be used for headers that you can't change, especially if you enable additional warnings.