问题
I try to write a parallel for loop using openMP V.2.0. In the middle of the parallel region I construct an Object which I would like to be constructed once per thread.
#pragma omp parallel for
for (long i = 0; i < static_cast<long>(general_triangles.size()); ++i)
{
TrianglePointer tri = general_triangles[i];
if (tri.GetClassification() == TO_CLASSIFY)
{
bool tri_has_correct_normal = true;
// --- Construct tree once per thread ---
Tree tree(*(gp_boolean_operator->mp_group_manager));
if (tree.IsTriangleExternal(tri, tri_has_correct_normal))
{
tri.SetClassification(IS_EXTERNAL);
}
}
}
Is there any keyword for constructing tree once per thread?
Do you suggest to use bood_thread_ptr instead?
回答1:
Consider untested code like this :
#pragma omp parallel
{
// --- Construct one tree in each per thread ---
Tree tree(*(gp_boolean_operator->mp_group_manager));
#pragma omp for
for (long i = 0; i < static_cast<long>(general_triangles.size()); ++i)
{
TrianglePointer tri = general_triangles[i];
if (tri.GetClassification() == TO_CLASSIFY)
{
bool tri_has_correct_normal = true;
if (tree.IsTriangleExternal(tri, tri_has_correct_normal))
{
tri.SetClassification(IS_EXTERNAL);
}
}
}
}
It shows that you can do all this inside portable, OS independent, OpenMP, and that you don't introduce an unnecessary static variable.
回答2:
This should work
gcc: static __thread
MSVC: static __declspec(thread)
However, for performance reasons it might be better to handle it manually. Use a vector with size that corresponds to the number of threads, and use the thread number to index the vector. If the element is NULL, the thread must construct it.
Also read: How to define thread-local local static variables?
Something like this (please note that it is untested, and I never use OMP myself because it does not offer the degree of control that I prefer to have over what actually happens).
std::vector<Tree *> trees;
trees.resize(omp_get_thread_limit());
#pragma omp parallel for
for (long i = 0; i < static_cast<long>(general_triangles.size()); ++i)
{
TrianglePointer tri = general_triangles[i];
if (tri.GetClassification() == TO_CLASSIFY)
{
bool tri_has_correct_normal = true;
// --- Construct tree once per thread ---
Tree *& tree = trees[omp_get_thread_num()];
if (tree == NULL)
tree = new Tree(*(gp_boolean_operator->mp_group_manager));
if (tree->IsTriangleExternal(tri, tri_has_correct_normal))
{
tri.SetClassification(IS_EXTERNAL);
}
}
}
// delete trees afterwards
来源:https://stackoverflow.com/questions/40586798/execute-piece-of-code-once-per-thread-in-openmp-without-default-constructor