我正在尝试并行化一个由第三方编写的大型程序。我不能透露代码,但我会尽量给出我想要做的最接近的例子。基于下面的代码。正如您所看到的,由于子句"parallel"位于while循环内部,因此线程的创建/销毁是在每次迭代中完成的,这是非常昂贵的。假设我不能移动初始化器…等等放到"while"循环之外
——基础代码
void funcPiece0()
{
// many lines and branches of code
}
void funcPiece1()
{
// also many lines and branches of code
}
void funcCore()
{
funcInitThis();
funcInitThat();
#pragma omp parallel
{
#pragma omp sections
{
#pragma omp section
{
funcPiece0();
}//omp section
#pragma omp section
{
funcPiece1();
}//omp section
}//omp sections
}//omp parallel
}
int main()
{
funcInitThis();
funcInitThat();
#pragma omp parallel
{
while(1)
{
funcCore();
}
}
}
我所要做的是避免每次迭代的创建/销毁操作,并在程序的开始/结束时执行一次。我尝试了许多替代"parallel"从句的变体。我基本上有相同的本质如下:(每个程序运行只有一个线程创建/销毁)——我尝试过,但在初始化函数中"非法访问"失败。
void funcPiece0()
{
// many lines and branches of code
}
void funcPiece1()
{
// also many lines and branches of code
}
void funcCore()
{
funcInitThis();
funcInitThat();
//#pragma omp parallel
// {
#pragma omp sections
{
#pragma omp section
{
funcPiece0();
}//omp section
#pragma omp section
{
funcPiece1();
}//omp section
}//omp sections
// }//omp parallel
}
int main()
{
funcInitThis();
funcInitThat();
while(1)
{
funcCore();
}
}
,
任何帮助将非常感激!谢谢!
OpenMP只在启动时创建工作线程。并行编译不会生成线程。如何确定线程是否已生成?
这可以做到!这里的关键是将循环移动到单个并行段中,并确保无论使用什么来确定是否重复,所有线程都将做出完全相同的决定。我使用了共享变量,并在检查循环条件之前进行了同步。
所以这个代码:
initialize();
while (some_condition) {
#pragma omp parallel
{
some_parallel_work();
}
}
可以转换成如下形式:
#pragma omp parallel
{
#pragma omp single
{
initialize(); //if initialization cannot be parallelized
}
while (some_condition_using_shared_variable) {
some_parallel_work();
update_some_condition_using_shared_variable();
#pragma omp flush
}
}
最重要的是要确保每个线程在代码的同一点做出相同的决定。
作为最后一个想法,本质上是将创建/销毁线程的开销(每次#pragma omp parallel的一段开始/结束时)转换为线程决策的同步开销。我认为同步应该更快,但是这里有很多参数在起作用,这可能并不总是。