OpenBSD supports symmetric multi-processors, SMP, commonly called multi-core CPUs.
SMP-enabled programs can run multiple cores simultaneously, generating results sooner. Amdahls' Law applies: any parallelized code that relies on results from non-parallel code is ultimately limited by the speed of the non-parallel part.
POSIX-compatible threading libraries are included in OpenBSD, if you have code (like fftw version 3) that can use it.
You can add non-supported OpenMP libraries to your OpenBSD system. OpenMP allows you to put simple directives (called pragmas) in your source C/C++/Fortran code to run relevant parts in parallel on the multiple cores of your hardware.
Other features such as CUDA or other GPU-related add-on processors are not available.
Since the OpenMP runtime is not included in OpenBSD base or via ports, how can
you develop code with the OpenMP pragmas? The answer is: you need
a “stub” runtime library that supports OpenMP programs but
behaves as a single-core machine. Also, use the fact that the clang and GNU
compilers support the -fopenmp
switch, even if OpenBSD doesn’t include their respective OpenMP runtime libraries.
The stub library was included with the flang compiler (OpenBSD 6.7 and earlier). But in OpenBSD 6.8 the flang compiler is not available. So you need your own.
cat > testopenmp.c << __end
#include <omp.h>
int main(void) {
return omp_get_num_threads();
}
__end
cc -fopenmp -I/usr/local/include -L/usr/local/lib \
-I . \
testopenmp.c myomp.o
./a.out
echo $?
and see an expected “1”. (cc here refers to the default compiler, a.k.a. clang cc).
For codes that use #pragma omp
statements, simply omit the
-fopenmp
directive and code that refers to omp_get_xxx() routines
will still work, because the stub supplies them. The compiler
will ignore #pragma
statements it doesn’t process.
A stub library needs an omp.h
file and an object file to link with.
Here is a simple omp.h file:
#ifndef __OMP_H
# define __OMP_H
extern void omp_set_num_threads (int);
extern int omp_get_num_threads (void);
extern int omp_get_max_threads (void);
extern int omp_get_thread_num (void);
extern int omp_get_num_procs (void);
#endif /* __OMP_H */
And here is the corresponding mylib.c stub file:
#include "omp.h"
extern void omp_set_num_threads (int a) {};
extern int omp_get_num_threads (void) {return 1;};
extern int omp_get_max_threads (void) {return 1;};
extern int omp_get_thread_num (void) {return 0;};
extern int omp_get_num_procs (void) {return 1;};
With this library you can write and partly debug OpenMP code for use on other operating systems.
This is not currently supported in “base” or add-on packages; you will have to add this yourself. For clang it’s not hard. For GCC it requires some time and resources (about 1500MB RAM and 6GB disk in /usr) to recompile your GCC compiler. A procedure and patch are described below.
Note: To do this, you should already be familiar with the OpenBSD ports system and making and compiling simple software ports. This is not for beginners. Seek help if you need to.
To setup OpenMP with clang, we will create two new ports: one for the static runtime library and a second for the dynamic run-time.
First download and extract the ports.tgz file as described in the OpenBSD Porter’s Handbook. Use the file that matches your version of OpenBSD.
Be sure to setup ports building under your own (or a purpose-made account) as described in the Handbook. Check that /usr/cache, /usr/distfiles, /usr/obj and /usr/ports/ have suitable ownership and permissions. Test by building the math/minisat package, which consists of a single download and a few simple compiles.
We show how to build and install packages for both static and dynamic libraries.
For OpenBSD 6.8, fetch this and that.
For OpenBSD 7.1, fetch this which provides both static and dynamic libraries.
For OpenBSD 6.8, unpack these two into /usr/ports/mystuff/lang/.
sysctl kern.version
## Verify OpenBSD 6.8
cd /usr/ports/mystuff/
tar xzf path/to/openmp1001.tar.gz
tar xzf path/to/stlibomp1001.tar.gz
For OpenBSD 6.8, verify the version 10.0.1 within the Makefile is correct then make it:
doas pkg_add ninja cmake xz
cd /usr/ports/mystuff/lang/stlibomp
clang -v (compare to V= within Makefile)
make package
doas TRUSTED_PKG_PATH=/usr/cache/pub/OpenBSD/6.8/package/amd64/all \
pkg_add stlibomp
cd /usr/ports/mystuff/lang/libomp
clang -v (compare to V= within Makefile)
vi Makefile
make package
doas TRUSTED_PKG_PATH=/usr/cache/pub/OpenBSD/6.8/package/amd64/all \
pkg_add libomp
For OpenBSD 7.1, the instructions are similar but shorter:
cd /usr/ports/mystuff/
tar xzf path/to/libomp_obsd71.tgz
cd /usr/ports/mystuff/lang/libomp
clang -v (compare to V= within Makefile)
grep VERSION Makefile
make package
doas TRUSTED_PKG_PATH=/usr/cache/pub/OpenBSD/7.1/package/amd64/all \
pkg_add libomp
(If you have problems, check file path, ownerships and o:rew permissions).
Note: There is no support for this configuration. Do not expect help from the misc@ or ports@ mailing lists, or from me.
For GCC, you can patch the GCC ports files and rebuild GCC to create new package files for OpenMP. (The patch adds .h and library files for OpenMP to the packages). Use this patch file (valid for OpenBSD 7.0) and tother patch file (valid for OpenBSD 7.1):
doas pkg_add xz bison gmake gmp libexecinfo
doas pkg_add libmpc mpfr
cd /usr/ports/lang/gcc/8
patch < path/to/gcc8_obsd70_gomp.patch # or _obsd71_
env FLAVOR="no_ada" make package
doas TRUSTED_PKG_PATH=/usr/cache/pub/OpenBSD/7.0/package/amd64/all \
pkg_add -u gcc-libs gcc g95 g++
This recompiles the four packages gcclibs, gcc, g++, g95, and installs them.
Note: There is no support for this configuration. Do not expect help from the misc@ or ports@ mailing lists, or from me.
OpenBSD Numerics |
OpenBSD Numerics - Parallelization
OpenBSD Numerics - Clusters |
OpenBSD Numerics - Examples
OpenBSD Numerics - Experiences pages