OpenMP is an implementation of multi-threading. Multi-threading is when one parallelizes code with the use of threads. Here a master thread running the program creates slave threads, by forking threads, and the task is divided between them. The threads run concurrently with the runtime environment allocating threads to different processors. The sections of code that are to run in parallel are marked with a pre-processor directive which will cause the forming of threads before the section is executed. Each thread will be given an ID, where the master thread has an ID of ''0''. After the execution of the parallel code the threads are then joined to the master thread that continues onward with the program. This is shown in Figure \ref{Fork} 

\begin{figure}[h]
\centering
\includegraphics[width=10cm]{report/background/Fork.png}
\caption{Image illustrating the Fork and Join of threads with OpenMP $^3$ }
\label{Fork}
\end{figure}
\footnotetext[3]{http://en.wikipedia.org/wiki/File:Fork\_ join.svg, accessed 2009-09-11. Available to all under the license of creative commons}

By default, each thread executes independently from the other hence giving good parallelism results. There are possibilities for work sharing constructs to divide the tasks between the threads such that each thread executes its allocated part of the work. Both task parallelism and data parallelism can be done using OpenMP in this way. 

\subsection*{Main Features}
The main OpenMP elements include thread construction, work sharing constructs, data environment management, synchronization of threads, user level runtime routines and environment variables. Thread creation happens when a thread is forked from a master thread, this is done by using the compiler directive ''\# pragma omp parallel''. For a broad overview of OpenMP language extentions see Figure \ref{languageextopenmp}.

\begin{figure}[h]
\centering
\includegraphics[width=10cm]{report/background/OpenMPlanguage.png}
\caption{Image illustrating language extentions of OpenMP $^4$ }
\label{languageextopenmp}
\end{figure}

The work sharing constructs is used to specify how one can assign independent work to one or all threads given the code that will be run. Here one has the option to specify with commands whether one wants a single (master) thread to perform a code block. One can perform calculations on specific sections of independent code blocks to different threads or use loop constructs to split up loop iterations among the threads. This can be done by adding to the command like this ''\# pragma omp parallel single''.

\footnotetext[4]{http://en.wikipedia.org/wiki/File:OpenMP\_ language\_ extensions.svg, accessed 2009-09-11. Available to all since the author has released it into public domain}

It is also possible to specify if the data is to be shared among the threads or if some of the variables are private by using data sharing attribute clauses. These are also specified in the command  such as in this example ''\# pragma omp parallel for private(i,j,k)''. The variables i ,j and k are not shared among the threads but rather each thread has a separate (private) copy.

With the use of OpenMP one is also in control of the scheduling one is to use by using the scheduling clauses. There are three types of scheduling to choose from static, dynamic and guided (which is a variation of dynamic). The static scheduler is used when one before execution decides which threads have which allocated iterations. Dynamic scheduling is when a thread is able to retrieve other iterations if its done earlier than others. 

When multi-threading one might come across a situation where one thread is done earlier than others and one might have problems with synchronizing between the threads before approaching another task. That is why in OpenMP one will find synchronization clauses. Here one can use commands to create barriers such all threads synchronize to that point before moving on. One is also able to specify that a region is critical such that one can avoid deadlocks. In critical sections only one thread is allowed to perform instructions at a time.

\subsection*{Thread creation and work sharing constructs}
By specifying ''parallel'' in the pragma one will fork into multiple threads that perform the instructions enclosed in the construct in parallel. By default OpenMP will set the amount of threads to that which matches the amount of cores available on the machine. Given that one is running on a Quad-core then 4 threads will be created. The original process will then be denoted as master thread and gets thread id 0. Once the threads are done they will be joined and the master process will continue running on a single core.

After indicating that code is to be run in parallel one can also specify how the threads should share the work load. An example would be the use of the ''for'' construct to specify that a loop is to be parallelized, and will result in that the loop iteration will be split among all the threads. There are also constructs that enable one thread to run while others are waiting or just signaling that a section of independent code can be run in parallel. 

\subsection*{Pros and cons}
One of the greatest strengths of OpenMP is that it is easy and simple to use, and that one does not have to deal with message passing. OpenMP directives automatically handle data layout and decomposition. The use of incremental parallelism results in no dramatic changes to ones code. Since one does not have to modify ones serial code much when using OpenMP makes it less likely to cause errors. OpenMP code can also be compiled for both serial and parallel code where in the serial compiler recognizes OpenMP syntax as comments. This results in that it will compile in both cases.

OpenMP is a great tool, but it also has its limitations. Such that it does not have reliable error handling. The scalability of an OpenMP program is bound by the memory architecture on which it runs. Currently it only runs efficiently on shared memory multiprocessor platforms. It also requires a compiler that supports OpenMP.

\subsection*{Performance expectations}
One could expect that running code on n cores would result in n times the speedup in OpenMP, but this is not the case because OpenMP is also affected by the common problems that apply to parallel computing generally. Parts of the code in an OpenMP program run on only the master process resulting that the speedup theoretical upper limit is limited by Amdahl's law, in that parts of the code are sequential. Another aspect is that the memory bandwidth also limits speedup since in shared memory often the same path is used for all threads to get data, and so they must be interleaved.  Other aspects resulting in overhead are synchronization and load balancing between all the threads. 