anderkve / FYS3150

https://anderkve.github.io/FYS3150
26 stars 14 forks source link

Compiling and linking with openMP #89

Closed ungvilde closed 1 year ago

ungvilde commented 1 year ago

I am a little confused by how I am supposed to compile and link with openMP. Without parallelisation, I build my code like this: CPATH=/opt/homebrew/include LIBRARY_PATH=/opt/homebrew/lib g++ main.cpp -std=c++11 -larmadillo src/* -I include -o main because I have a Mac silicone chip, and use header files in my main program. I have tried running: CPATH=/opt/homebrew/include LIBRARY_PATH=/opt/homebrew/lib g++ main.cpp -std=c++11 -larmadillo src/* -I include -Xpreprocessor -fopenmp -o main but I get an error like this: clang: error: linker command failed with exit code 1 (use -v to see invocation)

I find compiling/linking and all the flags and options quite confusion, so I would appreciate any help! Thank you!

anderkve commented 1 year ago

Hi @ungvilde!

(Sorry, in a bit of a hurry, so this reply will be a bit quick.)

I don't have a Mac to test with myself, but I suspect the problem is that what is hiding behind the g++ command in your case is actually Apple's version of the clang compiler ( shakes fist in direction of Apple ) , and Apple's version apparently do not support OpenMP out of the box. To verify that your g++ command is actually pointing to Apple clang, try running g++ --version and check the output.

I think you have two options:

1) Try to install the actual GNU g++ compiler (which should support OpenMP) via homebrew, and use that to compile your program. To e.g. install g++ version 12, you can use the command brew install gcc@12. That should give you access to a new terminal command g++-12, which should be the actual GNU g++. (Run g++-12 --version to confirm.) Try using that instead of g++ to compile your code. (When using g++-12 I don't think you'll need the -Xpreprocessor option.)

2) Try to install the "llvm" (non-Apple) version of the clang compiler, and use that to compile your program. See for instance this page: https://stackoverflow.com/questions/43555410/enable-openmp-support-in-clang-in-mac-os-x-sierra-mojave

If neither of these things work, try adding --verbose to your compilation command and paste/attach the full output here. Then we can see if we spot anything fishy.

anderkve commented 1 year ago

Just tagging @davidshope, @evenmn, @hkve and @Haakooto, in case some of you are Mac users and have more experience with this issue than I do.

ungvilde commented 1 year ago

It works with g++-12! Thank you so much @anderkve!

Og god bedring!

anderkve commented 1 year ago

Great, happy to hear it worked!

Og takk! :)

carbattron1313 commented 1 year ago

Hello, I have a similar problem because I also use IOS. I can compile a .cpp when using armadillo like this: g++ -O3 project4.cpp -std=c++11 -larmadillo -o project4.exe and when using openmp like this: g++-12 -O3 project4.cpp -fopenmp -o project4.exe.

The problem is that when I try to compile both at the same time (g++-12 -O3 project4.cpp -fopenmp -std=c++11 -larmadillo -o project4.exe) I get this error: fatal error: armadillo: no such file or directory

I would appreciate any help. Thank you in advance!

anderkve commented 1 year ago

Hi @carbattron1313!

The GNU g++ probably has a different set of default paths that it checks for header files and libraries, and armadillo is clearly not in those paths. So we need to figure out two paths to add to our g++-12 command, one include path (which we add by -I <some path>) and one library path (which we add by -L <some path>).

Either we can check exactly where the AppleClang g++ is looking for header files and libraries by doing

g++ -O3 project4.cpp -std=c++11 -larmadillo -o project4.exe --verbose

and go through the output to look for armadillo paths that contain the words include and lib.

The other alternative is to ask homebrew about what base directory it installed armadillo to, and find the correct paths that way. Try running

brew --prefix armadillo

and check the output. Presumably it will be something like /opt/homebrew/Cellar/armadillo or /usr/local/opt/armadillo. If you go to that folder I suspect you'll find subdirectories like /opt/homebrew/Cellar/armadillo/include and /opt/homebrew/Cellar/armadillo/lib. Try adding these to your g++-12 command, e.g.

g++-12 -O3 project4.cpp -fopenmp -std=c++11 -I /opt/homebrew/Cellar/armadillo/include -L /opt/homebrew/Cellar/armadillo/lib -larmadillo -o project4.exe
carbattron1313 commented 1 year ago

Thank you very much! It worked with the second option and the folder was /usr/local/opt/armadillo :)

anderkve commented 1 year ago

Very good :)

ungvilde commented 1 year ago

@anderkve Hi again. I have noticed that I get some kind of error related to Armadillo when I try to compile with g++-12 and an optimisation flag like -O2. Specifically, my terminal looks like this:

> In file included from /opt/homebrew/include/armadillo:386,
>                  from include/IsingModel.hpp:7,
>                  from src/IsingModel.cpp:1:
> In static member function 'static void arma::memory::release(eT*) [with eT = const long long int]',
>     inlined from 'arma::Mat<eT>::~Mat() [with eT = long long int]' at /opt/homebrew/include/armadillo_bits/Mat_meat.hpp:32:20,
>     inlined from 'arma::Mat<eT>::~Mat() [with eT = long long int]' at /opt/homebrew/include/armadillo_bits/Mat_meat.hpp:25:1,
>     inlined from 'arma::Col<long long int>::~Col()' at /opt/homebrew/include/armadillo_bits/Col_bones.hpp:25:7,
>     inlined from 'arma::sword arma::randi(const distr_param&)' at /opt/homebrew/include/armadillo_bits/fn_randi.hpp:138:32:
> /opt/homebrew/include/armadillo_bits/memory.hpp:137:9: warning: 'void free(void*)' called on unallocated object '<anonymous>' [-Wfree-nonheap-object]
>   137 |     free( (void *)(mem) );
>       |     ~~~~^~~~~~~~~~~~~~~~~
> In file included from /opt/homebrew/include/armadillo:532:
> /opt/homebrew/include/armadillo_bits/fn_randi.hpp: In function 'arma::sword arma::randi(const distr_param&)':
> /opt/homebrew/include/armadillo_bits/fn_randi.hpp:138:32: note: declared here
>   138 |   return as_scalar( randi<ivec>(uword(1), uword(1), param) );
>       |                     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
> In static member function 'static void arma::memory::release(eT*) [with eT = const long long int]',
>     inlined from 'arma::Mat<eT>::~Mat() [with eT = long long int]' at /opt/homebrew/include/armadillo_bits/Mat_meat.hpp:32:20,
>     inlined from 'arma::Mat<eT>::~Mat() [with eT = long long int]' at /opt/homebrew/include/armadillo_bits/Mat_meat.hpp:25:1,
>     inlined from 'arma::Col<long long int>::~Col()' at /opt/homebrew/include/armadillo_bits/Col_bones.hpp:25:7,
>     inlined from 'arma::sword arma::randi(const distr_param&)' at /opt/homebrew/include/armadillo_bits/fn_randi.hpp:138:32:
> /opt/homebrew/include/armadillo_bits/memory.hpp:137:9: warning: 'void free(void*)' called on unallocated object '<anonymous>' [-Wfree-nonheap-object]
>   137 |     free( (void *)(mem) );
>       |     ~~~~^~~~~~~~~~~~~~~~~
> /opt/homebrew/include/armadillo_bits/fn_randi.hpp: In function 'arma::sword arma::randi(const distr_param&)':
> /opt/homebrew/include/armadillo_bits/fn_randi.hpp:138:32: note: declared here
>   138 |   return as_scalar( randi<ivec>(uword(1), uword(1), param) );
>       |                     ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
> 

Do you know what might cause and/or solve this?

anderkve commented 1 year ago

Hi @ungvilde! Hmm, I don't know. I'd have to look into it more carefully. Is it an actual compiler error, or just a bunch of warnings? I.e. does the compilation complete? In the terminal output above I only see warnings, but no actual error message at which the compilation has stopped.

anderkve commented 1 year ago

Btw, if you have your current version of the code on GitHub, I can take a quick look. If so, just post a link. :)

ungvilde commented 1 year ago

@anderkve You are right, I was able to run despite the warnings! But they are abit scary and I don't understand why they show up... Only check out the code if you have time though, I have been able to get the necessary results, so at this point it would just be nice to know. My repo is here: https://github.com/ungvilde/FYS4150/tree/main/Project%204 I'm trying to run the main.cpp-file with openMP. Again, no need to check it out if you don't have time :)

anderkve commented 1 year ago

I've had a quick look now, but I can't figure out what the issue is. I can't reproduce it on my system (with g++-12, -O2 and -fopenmp), and I can't find anything about it on the Armadillo forum for bug reports: https://gitlab.com/conradsnicta/armadillo-code/-/issues/?sort=updated_desc&state=all&first_page_size=20

At least I don't think this is due to a mistake in the code you have written. The warning message simply points back to the line where you #include <armadillo> and then further back to a line inside the armadillo library.

The actual warning message says that a line in the armadillo library seems to "free" (deallocate) some memory that actually hasn't been allocated yet. This is in general a type of warning that I'd be slightly concerned about, but in this case I wouldn't worry too much.

If it only appears when running with -O2 or -O3, but not with -O0 or -O1, you can of course try running some small test two times, once with -O1 and once with -O2, and check that the results look the same. (Keep in mind that they won't be exactly the same, unless the random number seed is also the same in both runs.)