Why is thread_local not applicable to non-stationary data elements and how to implement thread-local non-static data elements?

Why thread_localnot apply to non-stationary data elements? The accepted answer to this question says: "There is no point in creating non-static structures or members of the thread-local class." Honestly, I see many good reasons to make non-static data members thread local.

Suppose we have some kind of ComputeEnginemember function computeSomethingthat is called many times in a row. Some of the work inside a member function can be performed in parallel. For this, each thread needs some ComputeHelperthat provides, for example, auxiliary data structures. So we really want to:

class ComputeEngine {
 public:
  int computeSomething(Args args) {
    int sum = 0;
    #pragma omp parallel for reduction(+:sum)
    for (int i = 0; i < MAX; ++i) {
      // ...
      helper.xxx();
      // ...
    }
    return sum;
  }
 private:
  thread_local ComputeHelper helper;
};

Unfortunately, this code will not compile. Instead, we could do the following:

class ComputeEngine {
 public:
  int computeSomething(Args args) {
    int sum = 0;
    #pragma omp parallel
    {
      ComputeHelper helper;
      #pragma omp for reduction(+:sum)
      for (int i = 0; i < MAX; ++i) {
        // ...
        helper.xxx();
        // ...
      }
    }
    return sum;
  }
};

However, this will lead to creation and destruction ComputeHelperbetween successive calls computeSomething. Assuming construction ComputeHelperis expensive (for example, due to the allocation and initialization of huge vectors), we can reuse ComputeHelperbetween successive calls. This leads me to the following approach:

class ComputeEngine {
  struct ThreadLocalStorage {
    ComputeHelper helper;
  };
 public:
  int computeSomething(Args args) {
    int sum = 0;
    #pragma omp parallel
    {
      ComputeHelper &helper = tls[omp_get_thread_num()].helper;
      #pragma omp for reduction(+:sum)
      for (int i = 0; i < MAX; ++i) {
        // ...
        helper.xxx();
        // ...
      }
    }
    return sum;
  }
 private:
  std::vector<ThreadLocalStorage> tls;
};
  • thread_local ? ? , - ?
  • ?
+4
2

, thread_local , . , public/private/protected , . , , - TLS .

, , boost::thread_specific_ptr. .

+4

, , (, TEB Windows

, , .

, - - ( , ),

, , , -, .

+2

Source: https://habr.com/ru/post/1605657/


All Articles