通过使用OpenMP并行化来减少时间

Reducing time by using OpenMP parallelization

本文关键字:时间 并行化 OpenMP      更新时间:2023-10-16

我试图通过使用OpenMP并行化(c++)来减少我的算法的计算时间。我试过简单的东西,但我不太明白它是如何工作的…

下面是我的代码:
int nthread = omp_get_max_threads();
#pragma omp parallel for num_threads(nthread)
for(int i=0;i<24;++i)
  std::cout << omp_get_thread_num() << std::endl;

在我的电脑上,nthread = 6。我不明白为什么输出是:

0
0
0
... (24 times)

为什么它不给我从0到5的数字?

如果我理解得好(如果我错了请纠正我),在这段代码中,有6个线程将执行std::cout命令。那么,为什么我只有"0"作为输出呢?

第二件事:我想在每个线程中执行循环的某个部分。我想把我的循环分成6个(nthread)不同的部分,这样每个部分都可以由不同的线程执行。

这里,我希望我的6个线程都执行

std::cout << omp_get_thread_num() << std::endl;

4次。

我该怎么做?我试过了:

#pragma omp parallel for num_threads(nthread)
for(int i=omp_get_thread_num()*(24/nthread);i<(omp_get_thread_num()+1)*(24/nthread);++i)
  std::cout << omp_get_thread_num() << std::endl;

正确吗?我得到的输出是:

0
0
0
0

终端中只有"0"线程而没有其他线程是正常的吗?

谢谢

只是部分答案,但我不能对此保持沉默

我试过了:

for(int i=omp_get_thread_num()*(24/nthread);i<(omp_get_thread_num()+1)*(24/nthread);++i)
  std::cout << omp_get_thread_num() << std::endl;

正确吗?

不,这不对,一点也不对!代码正在执行跨线程划分迭代的工作,更好的模型是

for(int i=0;i<max_iters;++i)
  do work depending on i

和编译器/运行时将负责在线程之间划分工作。每个线程将获得自己的i值集来处理。

这个简单的模式只有在循环中的每个任务都独立于其他任务时才正确,所以work(i)work(i-1)之间没有依赖关系。但在一开始,这可能足以让你开始。

至于你问题的其余部分,看起来好像你实际上并没有并行运行代码。我建议替换

int nthread = omp_get_max_threads();
#pragma omp parallel for num_threads(nthread)

#pragma omp parallel for 

也就是说,保留默认设置的线程数。如果这不起作用,用你进一步调查的结果来修改你的问题。再看看SO,我敢肯定你会找到一个重复的

RyanP,你完全正确,我错过了关键字openmp。我添加了它,现在它工作得很好!非常感谢。

也感谢High Performance Mark的回答,

#pragma omp parallel for

对于我想做的事已经足够了。

我知道

for(int i=omp_get_thread_num()*(24/nthread);i<(omp_get_thread_num()+1)*(24/nthread);++i)
  std::cout << omp_get_thread_num() << std::endl;

是错误的,但由于我尝试的其他方法都不起作用,我尝试了一些疯狂的方法。谢谢你的解释,现在更清楚了。

为了解决我的问题,我只需在CMakeList.txt中添加以下几行:

find_package(OpenMP)
if (OPENMP_FOUND)
    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()

效果很好。

谢谢大家