Seg fault: c++17 std parallel for_each and DynamicMatrix

Issue #381 wontfix
Ecolss Logan created an issue

I’ve been testing a use-case, example code goes as follows,

#include <blaze/Blaze.h>
#include <execution>
#include <iostream>
#include <vector>

int main(int argc, char** argv) {
  // determine how many workers run in parallel
  std::vector<size_t> workers(std::stoi(argv[1]));

  std::for_each(std::execution::par, workers.begin(), workers.end(), [&](size_t x) {
    blaze::DynamicMatrix<float> mat;
    mat.resize(10000, 50);
    mat = 1.0f;

    for (size_t i = 0; i < blaze::rows(mat); ++i) {
      // This line seems to be the place where segfault happens
      blaze::row(mat, i) = blaze::row(mat, 0);
    }
    std::cout << blaze::sum(mat) << std::endl;
  });
}

Env:

  • Mac OSX Catalina, 10.15.7.
  • C++ compiler is GNU G++-10.

Compiled like this,

g++ -std=c++17 -O3 -DNDEBUG a.cpp -ltbb -I /usr/local/include -IX/ -L /usr/local/lib -fopenmp

If run with 1 worker, all is good, no segfault.

But if run with >1 workers, segfault happens, but not constantly.

>>> ./a.out 2
500000
terminate called after throwing an instance of 'std::runtime_error'
zsh: segmentation fault  ./a.out 2

line14 seems to be the cause, since if I comment out it, the code won’t seg fault.

The problem is I don’t understand why that line would be an issue?

Comments (3)

  1. Klaus Iglberger

    Hi Ecolss!

    You are mixing several kinds of parallelization: TBB, the parallel execution policy of std::for_each, and OpenMP, which is used inside Blaze operations. The problem should be gone if you either don’t use OpenMP or don’t parallelize Blaze (see Serial Execution).

    Best regards,

    Klaus!

  2. Ecolss Logan reporter

    Hi @Klaus Iglberger , highly appreciate your quick response!

    Just now tried you suggestion, it worked!

    BTW, what if my production codebase involves both tbb and openmp, and now need to involve Blaze?

    or don’t parallelize Blaze (see Serial Execution).

    If I do this, will Blaze be slower?

  3. Klaus Iglberger

    Hi Ecolss!

    The problem with OpenMP is that you may not create a parallel section within another parallel section. The OpenMP parallelization of Blaze assumes that it needs to create the parallel section itself. Instead of OpenMP you can use the C++11-Thread backend by passing -DBLAZE_USE_CPP_THREADS to the compiler. Then Blaze will use its own thread pool instead of OpenMP. This should work in combination with OpenMP and TBB, but I cannot give any guarantees.

    In order to rate the performance with or without internal parallelization in an OpenMP/TBB-parallel environment you'll have to run benchmarks.

    Best regards,

    Klaus!

  4. Log in to comment