与std::线程结合使用的嵌套openMP并行化
Nested openMP parallelisation in combination with std::thread
大家好,
我目前在图像处理领域从事一个更大的项目。我正在使用Visual Studio 2013进行开发(没有商量余地)。我不想再麻烦你了,我的问题是这样的:
我有两个动作必须并行运行:
-
线性方程组的迭代解(使用1-2个线程)
-
一个相当复杂的过程,涉及图像到图像的配准。(使用所有剩余线程)
为了知道哪些图像需要配准,需要线性方程组的近似解。因此它们需要同时运行。(感谢Z玻色子指出了这些信息的缺失)。迭代解决方案不断运行,并在每次成功的图像配准后得到通知。
代码将在24核系统上运行。
目前使用openMP和"#pragma omp parallel for"实现图像配准。迭代解决方案正在使用std::线程启动,并在内部使用openMP"#pragma omp parallel for"。
现在我知道,根据omp文档,发现嵌套并行性的omp线程将使用其线程组来执行代码。但我认为这在我的情况下不起作用,因为它是一个std::线程启动第二个并行程序。
为了更好地理解,这里有一个示例代码:
int main()
{
std::thread * m_Thread = new std::thread(&IterativeSolution);
#pragma omp parallel for
for(int a = 0; a < 100; a++)
{
int b = GetImageFromApproximateSolution();
RegisterImages(a,b);
// Inform IterativeSolution about result of registration
}
}
void IterativeSolution()
{
#pragma omp parallel for
for(int i = 0; i < 2; i++)
{
//SolveColumn(i);
}
}
void RegisterImage(int a, int b)
{
// Do Registration
}
在这一点上我的问题是:上面的代码会创建太多的线程吗?如果是这样,下面的代码能解决问题吗?int main()
{
// The max is to avoid having less than 1 thread
int numThreads = max(omp_get_max_threads() - 2, 1);
std::thread * m_Thread = new std::thread(&IterativeSolution);
#pragma omp parallel for num_threads(numThreads)
for(int a = 0; a < 100; a++)
{
int b = GetImageFromApproximateSolution();
RegisterImages(a,b);
// Inform IterativeSolution about result of registration
}
}
void IterativeSolution()
{
#pragma omp parallel for num_threads(2)
for(int i = 0; i < 2; i++)
{
//SolveColumn(i);
}
}
void RegisterImage(int a, int b)
{
// Do Registration
}
这会产生OpenMP标准中未定义的行为。我测试过的大多数实现将为第一个示例中的两个并行区域分别创建24个线程,总共48个线程。第二个例子不应该创建太多的线程,但由于它依赖于未定义的行为,它可能会在没有警告的情况下做任何事情,从崩溃到将您的计算机变成果冻状的物质。
既然您已经在使用OpenMP,我建议您通过简单地删除std::线程,并使用嵌套的OpenMP并行区域来使其符合OpenMP标准。你可以这样做:
int main()
{
// The max is to avoid having less than 1 thread
int numThreads = max(omp_get_max_threads() - 2, 1);
#pragma omp parallel num_threads(2)
{
if(omp_get_thread_num() > 0){
IterativeSolution();
}else{
#pragma omp parallel for num_threads(numThreads)
for(int a = 0; a < 100; a++)
{
int b = GetImageFromApproximateSolution();
RegisterImages(a,b);
// Inform IterativeSolution about result of registration
}
}
}
}
void IterativeSolution()
{
#pragma omp parallel for num_threads(2)
for(int i = 0; i < 2; i++)
{
//SolveColumn(i);
}
}
void RegisterImage(int a, int b)
{
// Do Registration
}
您可能需要向您的环境添加环境变量定义OMP_NESTED=true
和OMP_MAX_ACTIVE_LEVELS=2
,或者更多,以启用嵌套区域。这个版本的优点是完全在OpenMP中定义,可以移植到任何支持嵌套并行区域的环境中。如果您的版本不支持嵌套的OpenMP并行区域,那么您建议的解决方案可能是剩下的最佳选择。
- OpenMP 嵌套未关闭
- 如何使用 OpenMP 减少嵌套循环?
- 具有动态数组分配的OpenMP嵌套循环
- OpenMP 和不平衡嵌套循环
- OpenMP 嵌套循环处理性能
- 嵌套循环 OpenMP 并行化、私有索引还是公共索引?
- 将 for 循环与嵌套的 while 循环并行化时出现 OpenMP 分段错误
- 用于在一维数组上嵌套循环操作的正确 openmp 指令
- 在 C 中并行化嵌套循环的几种方法之间的差异,C++使用 OpenMP
- 使用MPI/OpenMP的C 程序带有派生数据类型(嵌套类对象)容器
- OpenMP 如何知道嵌套了多少个循环实例
- OpenMP 按需嵌套并行性
- 有效地在小环上使用OpenMP,并具有非常大的嵌套回路
- 嵌套并行区域 OpenMP
- OpenMP,嵌套循环设计策略
- 嵌套矢量化 OpenMP 循环,在最内层循环中具有多行代码
- OpenMP 嵌套循环,每个"for"循环之间都有代码
- OpenMP G++ 错误:折叠的循环未完全嵌套
- Openmp:嵌套循环和分配
- 与std::线程结合使用的嵌套openMP并行化