OpenMP 6.0
openmp.org
openmp.org
1) ray tracing. Looping over all the pixels in an image using ray tracing to determine the color of each pixel. The algorithm and data structures are complex but don't change during the rendering. N cores is about N times as fast.
2) in Solvespace we had a small loop which calls a tessellation function on a bunch of NURBS surfaces. The function was appending triangles to a list, so I made a thread-local list for each call and combined them after to avoid writes to shared data structure. Again N times faster with very little effort.
The code is also fine to build single threaded without change if you don't have OpenMP. Your compiler will just ignore the #pragmas.
True (or with Intel TBB), however as someone with a lot of experience optimising HPC algorithms for rendering, geometry processing and simulation, there are caveats, and quite often you can get situations where the existing code that is parallelised this way more naively can spend disproportionate amounts of CPU usage on spinlocks in OpenMP or TBB instead of doing useful work. (I've also noticed the same thing happening with Rayon in Rust).
Sometimes I've looked at code other colleagues have "parallelised" this way, and they've said "yes, it's using multiple threads", but when you profile it with perf or vtune, it's clearly not really doing that much *useful* parallel work, and sometimes it's even slower than single-threaded from a wall-clock standpoint, and people just didn't check if it was faster, they just looked at the CPU usage, and didn't notice the spinlocks.
The best I've found so far:
https://cdn.kernel.org/pub/linux/kernel/people/paulmck/perfb...
And some other good reading:
https://www.amazon.com/Systems-Performance-Brendan-Gregg/dp/...
https://fgiesen.wordpress.com/2014/08/18/atomics-and-content...
https://travisdowns.github.io/blog/2020/07/06/concurrency-co...
Or, pre-allocate the memory and let each thread write to its own subset of the final collection and avoid the combine step entirely. This works regardless of the number of threads you use so long as you know the maximum amount of memory you might need to allocate. If it has no calculable upper bound, you will need to use other techniques.
So easiest depends on the target audience.
https://www.intel.com/content/www/us/en/docs/oneapi/optimiza...
gcc also provides support for NVidia and AMD GPUs
https://gcc.gnu.org/wiki/Offloading
Here is an example how you can use openmp for running a kernel on a nvidia A100:
https://people.montefiore.uliege.be/geuzaine/INFO0939/notes/...
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
void saxpy(int n, float a, float *x, float *y) {
double elapsed = -1.0 \* omp_get_wtime();
// We don't need to map the variable a as scalars are firstprivate by default
#pragma omp target teams distribute parallel for map(to:x[0:n]) map(tofrom:y[0:n])
for(int i = 0; i < n; i++) {
y[i] = a * x[i] + y[i];
}
elapsed += omp_get_wtime();
printf("saxpy done in %6.3lf seconds.\n", elapsed);
}
int main() {
int n = 2000000;
float *x = (float*) malloc(n*sizeof(float));
float *y = (float*) malloc(n*sizeof(float));
float alpha = 2.0;
#pragma omp parallel for
for (int i = 0; i < n; i++) {
x[i] = 1;
y[i] = i;
}
saxpy(n, alpha, x, y);
free(x);
free(y);
return 0;
}It was okay for basic embarrassingly parallel for loops. I ended up not using any more advanced features, because apart from even worse compiler support, non-trivial multi-threading in C without any safeguards is just too easy to mess up.
> In ncnn project, we implement a minimal openmp runtime for webassembly target
> It only works for #pragma omp parallel for num_threads(N)
[1] https://github.com/emscripten-core/emscripten/issues/13892
[2] https://github.com/Tencent/ncnn/blob/master/src/simpleomp.h
[3] https://github.com/Tencent/ncnn/blob/master/src/simpleomp.cp...