-
Emmanuel Lanti authoredEmmanuel Lanti authored
libraries.tex 9.37 KiB
\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: