\renewcommand{\FIGREP}{src/libraries/figures} \section{Libraries} \label{sec:libraries} \intersec{izar} \subsection{Compiling with libraries} \label{sec:comp-with-libr} \begin{frame} \frametitle{Libraries} \framesubtitle{} \begin{itemize} \item Libraries are a collection of pre-compiled pieces of code that can be reused in other programs \item One almost always uses libraries in our programs, \eg{} \cmd{iostream}, \cmd{vector} in C++, \cmd{stdio} in C \pause \item In general, a library consists of a header file, \cmd{cmath.h}, and a binary object, \cmd{libm.so} \item At compile time (pre-processing) you provide the headers \item At linking time you provide the object files \end{itemize} \end{frame} \begin{frame}[fragile] \frametitle{Libraries} \framesubtitle{A simple example} \begin{itemize} \item Someone wrote an awesome math library called \cmd{mymath} providing the \cmd{squared} function \item Let's us it! \end{itemize} \cxxfile[title={libraryExample/main\_bad.c}]{examples/libraryExample/main_bad.c} \pause \begin{bashcode} $> gcc -Werror -Wall main_bad.c -o main main_bad.c: In function ‘main’: main_bad.c:4:39: error: implicit declaration of function ‘squared’ 4 | printf("The square of 2.0 is %f\n", squared(2.0)); \end{bashcode}%$ \begin{itemize} \item Our program doesn't know about this \cmd{squared} function \end{itemize} \end{frame} \begin{frame}[fragile] \frametitle{Libraries} \framesubtitle{A (better) simple example} \begin{itemize} \item Let's add the header file to declare the \cmd{squared} function \end{itemize} \cxxfile[title={libraryExample/main\_correct.c}]{examples/libraryExample/main_correct.c} \pause \begin{bashcode} $> gcc -Werror -Wall main_correct.c -o main main_correct.c:2:10: fatal error: mymath.h: No such file or directory 2 | #include "mymath.h" | ^~~~~~~~~~ compilation terminated. \end{bashcode}%$ \begin{itemize} \item We need to tell the compiler where to find this header file \end{itemize} \end{frame} \begin{frame}[fragile] \frametitle{Libraries} \framesubtitle{Include header files} \begin{itemize} \item When you have an \cmd{#include} or \cmd{use} (f90) in your code, the compiler must know where to look for them \item It has some default paths it will always look in, \eg{} system paths and current path, but you can supply your own with the \cmd{-I} option \end{itemize} \textbf{Example}: \begin{itemize} \item Let's assume the \cmd{mylibrary.h} header is located in \cmd{~/mycode/includes/mylibrary.h} \item The source code that uses it is located in \cmd{~/mycode/src/source.cpp} \item Here you have two options: \begin{enumerate} \item You put the library path in the source file, \ie{} \cmd{#include "../includes/mylibrary.h"} \item You simply use \cmd{#include "mylibrary.h"} and tell the compiler (pre-processor) where to look for it \begin{bashcode} gcc -I~/mycode/includes source.cpp \end{bashcode} \end{enumerate} \end{itemize} \end{frame} \begin{frame}[fragile,t] \frametitle{Libraries} \framesubtitle{A (almost there) simple example} \begin{itemize} \item Let's add the correct option to the compiler \end{itemize} \begin{bashcode} $> gcc -Imylibrary -Werror -Wall main_correct.c -o main /usr/bin/ld: /tmp/ccBYOiab.o: in function `main': main_correct.c:(.text+0x11): undefined reference to `squared' collect2: error: ld returned 1 exit status \end{bashcode}%$ \begin{itemize} \item Now we are missing the actual definition of the function \item Two possibilities, the bad and the correct \end{itemize} \begin{bashcode} $> gcc -Imylibrary main_correct.c -o main mylibrary/libmymath.so # the bad \end{bashcode}%$ \begin{bashcode} $> gcc -Imylibrary main_correct.c -o main -Lmylibrary -lmymath # the correct \end{bashcode}%$ \end{frame} \begin{frame}[fragile,t] \frametitle{Libraries} \framesubtitle{Linking options} \begin{itemize} \item To link a library to your executable you need to tell the linker \begin{itemize} \item Where is the library: \cmd{-L<PATH/TO/LIBRARY>} \item Which library you want to use: \cmd{-l<LIB_NAME>} \end{itemize} \item The linking options should be put at the end (after the files against which they will be linked) \begin{bashcode} $> gcc -Imylibrary main_correct.c -o main -Lmylibrary -lmymath # OK \end{bashcode}%$ \begin{bashcode} $> gcc -Lmylibrary -lmymath -Imylibrary main_correct.c -o main # NOT OK \end{bashcode}%$ \item In some cases, the order with which the library names appear matters. Read the linker documentation! \end{itemize} \vfill \pause \textbf{Summary:} \begin{bashcode} $> gcc -I<PATH/TO/HEADERS> code.c -L<PATH/TO/LIBRARY> -l<LIBRARY_NAME> \end{bashcode}%$ \end{frame} \subsection{Static and shared libraries} \label{sec:stat-shar-libr} \begin{frame}[fragile,b] \frametitle{Static and shared libraries} \framesubtitle{} \begin{minipage}{0.49\linewidth} \begin{itemize} \item Name is \cmd{libXYZ.a} \item Lib linked at compile time \item If the library changes, must recompile the program \item Executable is larger \end{itemize} \end{minipage} \hfill \begin{minipage}{0.49\linewidth} \begin{itemize} \item Name is \cmd{libXYZ.so} \item They are ``linked'' to the executable \item A table is created at compile time and libs are loaded at runtime \item Libs can be updated independently \item Smaller executable \end{itemize} \end{minipage} \addimage[width=10cm]{\FIGREP/library_static_shared}{3.0cm}{3.3cm} \end{frame} \begin{frame}[t,fragile] \frametitle{Shared libraries} \framesubtitle{Loading the libraries} The following applies for shared libraries, but doesn't impact static libraries \begin{itemize} \item Shared libraries are not included in the executable, but only linked and loaded at runtime \item You can check them with \cmd{ldd} \begin{bashcode} $> ldd main linux-vdso.so.1 (0x00007ffc716df000) libmymath.so => not found libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f80e0657000) /lib64/ld-linux-x86-64.so.2 (0x00007f80e0846000) \end{bashcode}%$ \item To tell the OS where is the library to load, we use the variable \cmd{LD_LIBRARY_PATH} \item For example, prepend your path \begin{bashcode} $> export LD_LIBRARY_PATH=/path/to/the/library:$LD_LIBRARY_PATH \end{bashcode} \end{itemize} \end{frame} \begin{frame}[exercise] \frametitle{Compilation} \framesubtitle{Exercise compilationWithLibrary} \begin{itemize} \item Go to the directory \cmd{compilationWithLibrary} \item Compile the code \cmd{main.F90} with shared library \cmd{libsaxpy.so} \item Execute the code \item Check the results according to the solution of exercise \cmd{simpleCompilation} \end{itemize} \end{frame} \begin{frame}[exercise] \frametitle{Compilation} \framesubtitle{BONUS: Exercise compilationWithMixLibrary} \begin{itemize} \item To mix static and shared libraries use: \cmd{-Wl,-Bstatic static_library -Wl,-Bdynamic shared_library} \item Go to the directory \cmd{compilationWithMixLibrary} \item Compile the code \cmd{main.c} with static library \cmd{libmax.a} and shared library \cmd{libsaxpy.so} \item Execute the code \item Check the results according to the solution of exercise \cmd{simpleCompilation} \end{itemize} \end{frame} \subsection{Important libraries in HPC} \label{sec:import-libr-hpc} \begin{frame} \frametitle{A few notable libraries} \framesubtitle{} Don't reinvent the wheel, use a library! \vfill \begin{itemize} \item Basic Linear Algebra Subprograms (BLAS) \begin{itemize} \item Provides routines to perform basic linear algebra operations (vector addition, dot product, etc.) \item OpenBLAS, Intel MKL, cuBLAS, rocBLAS, etc. \end{itemize} \item Linear Algebra Package (LAPACK) \begin{itemize} \item Provides routines for solving systems of linear equations \item OpenBLAS, Intel MKL, Netlib LAPACK and ScaLAPACK, etc. \end{itemize} \item Other solvers (direct and iterative) \begin{itemize} \item MUMPS, SuperLU, PETSc, PARDISO, etc. \end{itemize} \item Fourier transforms \begin{itemize} \item FFTW, cuFFT, intel MKL, etc. \end{itemize} \item And many others! \end{itemize} \end{frame} \begin{frame}[t,fragile] \frametitle{BONUS: Making your own library} \framesubtitle{} \begin{itemize} \item Creating static library \cmd{libmylib.a} from different object files \cmd{prog*.o} \begin{consoleoutput} $ gcc -c prog1.c prog2.c prog3.c ... progn.c $ ar -rv libmylib.a prog1.o prog2.o prog3.o ... progn.o \end{consoleoutput} \item Creating shared library \cmd{libmylib.so} from different object files \cmd{prog*.o} \begin{consoleoutput} $ gcc -fPIC -c prog1.c prog2.c prog3.c ... progn.c $ gcc -o libmylib.so -shared prog1.o prog2.o prog3.o ... progn.o \end{consoleoutput} \end{itemize} \end{frame} %%% Local Variables: %%% mode: latex %%% TeX-master: "../../SCM_slides" %%% End: