openMP multithreading c++

openMP multithreading c++

本文关键字:c++ multithreading openMP      更新时间:2023-10-16

来自我以前的一篇文章c++线程/boost线程的高效使用方法

我知道我可以通过使用openMP将串行程序转换为并行程序并更改:

int thread_count=8;
for(int i=1;i<100000;i++)
{
do_work(i,record);
}

int thread_count=8;
#pragma omp parallel for
for(int i=1;i<100000;i++)
{
do_work(i,record);
}

如何完全并行化嵌套的for循环?是通过改变

int thread_count=8;
for(int i=1;i<100000;i++)
{
   for(int j=1;j<100000;j++){
do_work(i,j,record);
 }
}

int thread_count=8;
#pragma omp parallel for
for(int i=1;i<100000;i++)
{
   #pragma omp parallel for
   for(int j=1;j<100000;j++){
do_work(i,j,record);
 }
}

最大并行化?谢谢你。

这样做通常不是一个好主意。这意味着在最外层循环的每次迭代中创建(更可能只是管理)线程池的嵌套并行性。

然而,如果只并行最外层的循环对你来说是不够的(在大多数情况下应该是),你可以考虑使用collapse(2)子句来融合ij循环,并并行处理整个(i,j)域。

对于特殊需求的最后一个解决方案,如果您真的需要嵌套并行而不需要OpenMP parallel开销,则创建单个parallel区域并根据其id手动分配工作给线程。这并不像放入编译器指令那么简单,但这也不是特别复杂…但是,只有当您有非常特殊的需求,而您无法用通常的OpenMP结构/哲学以令人满意的方式解决这些需求时,您才应该考虑使用OpenMP。

首先,要使用特定的线程数,您应该使用:

int thread_count=8;
#pragma omp parallel for num_threads(thread_count)
for(int i=1;i<100000;i++)
{
do_work(i,record);
}

如果你想嵌套,你需要用omp_set_nested(1)打开它。

如果每个线程都在做类似的工作,为了在并行化中实现最大性能,您应该确保线程总数对应于内核/虚拟处理器的数量(在超线程的情况下),因此使用omp_get_max_threads()来检查它。如果您使用嵌套并行化,线程数是每个级别上线程数的乘积,因此您可以轻松地生成超出虚拟处理器有效支持的线程数。

你建议的方式不会给你性能提高,因为每个线程仍然执行单个do_work(...)。但是,如果单个do_work()足够长,并且它本身包含一些循环,那么如果在其中应用第二级并行处理,您可能会获得一些速度提升。通过这种方式,您的线程运行不同长度的任务,并且如果在给定时刻有可用的资源,调度器可能会挤出一些短任务。

但是对于这个,我不推荐嵌套的OMP -在我的实验中,应用第二级#pragma omp for实际上降低了速度。然而,如果您使用不同的多线程机制,您可能仍然会得到一些改进,例如:使用OMP进行外部并行化,使用boost线程池或使用WinApi _beginthreadex(...)进行内部循环。