带有嵌套循环的 OpenMP
OpenMP with nested loops
我有几个函数应该连续应用于某些结构的矩阵。对于单线程,我使用以下代码:
for(int t = 0; t < maxT; ++t)
{
for(int i = 0; i < maxI; ++i)
for(int j = 0; j < maxJ; ++j)
function1(i, j);
for(int i = 0; i < maxI; ++i)
for(int j = 0; j < maxJ; ++j)
function2(i, j);
}
现在我正在尝试并行化该代码:
#pragma omp parallel
{
for(int t = 0; t < maxT; ++t)
{
#pragma omp single
function3(); // call this function once (once for each iteration of t)
#pragma omp for
for(int i = 0; i < sizeI; ++i)
for(int j = 0; j < sizeJ; ++j)
function1(i, j);
#pragma omp for
for(int i = 0; i < sizeI; ++i)
for(int j = 0; j < sizeJ; ++j)
function2(i, j);
}
}
是否正确?
它是否以重用线程的方式工作(不在主循环中创建新线程组)?
更新:显式屏障确实没有必要。
实际上,当我问这个问题时,我似乎感到困惑 - 代码示例可以正常工作。现在的问题是:是否可以在#pragma omp parrallel 之后调用一次函数(代码中的注释行)(不要在每次迭代中在每个线程中调用 function3)。有 #pragma omp atomic 来调用增量运算符和其他一些运算符,但是如果我想调用任意函数的单个实例(或者,通常,执行一段代码)?
马克的评论。我假设我将在我的并行函数中处理数据竞争。这里唯一的问题是:stl 容器在使用 OpenMP 时不仅仅是线程安全的吗?即,如果我想从多个线程在 std::list 中 push_back(),我仍然需要手动锁定该列表。
更新 2:我发现要 运行 并行部分中的单个操作,需要使用 #pragma omp single。那么,这个问题就结束了。
是的,这将创建一个并行区域,其中每个线程将在外循环上迭代 t
,并在线程之间拆分 i
循环迭代的工作。
请注意,#pragma omp for
的末尾有一个隐式屏障,因此您无需也编写显式屏障。可以使用 nowait
子句(即 #pragma omp for nowait
)删除此隐式障碍。
我有几个函数应该连续应用于某些结构的矩阵。对于单线程,我使用以下代码:
for(int t = 0; t < maxT; ++t)
{
for(int i = 0; i < maxI; ++i)
for(int j = 0; j < maxJ; ++j)
function1(i, j);
for(int i = 0; i < maxI; ++i)
for(int j = 0; j < maxJ; ++j)
function2(i, j);
}
现在我正在尝试并行化该代码:
#pragma omp parallel
{
for(int t = 0; t < maxT; ++t)
{
#pragma omp single
function3(); // call this function once (once for each iteration of t)
#pragma omp for
for(int i = 0; i < sizeI; ++i)
for(int j = 0; j < sizeJ; ++j)
function1(i, j);
#pragma omp for
for(int i = 0; i < sizeI; ++i)
for(int j = 0; j < sizeJ; ++j)
function2(i, j);
}
}
是否正确? 它是否以重用线程的方式工作(不在主循环中创建新线程组)?
更新:显式屏障确实没有必要。
实际上,当我问这个问题时,我似乎感到困惑 - 代码示例可以正常工作。现在的问题是:是否可以在#pragma omp parrallel 之后调用一次函数(代码中的注释行)(不要在每次迭代中在每个线程中调用 function3)。有 #pragma omp atomic 来调用增量运算符和其他一些运算符,但是如果我想调用任意函数的单个实例(或者,通常,执行一段代码)?
马克的评论。我假设我将在我的并行函数中处理数据竞争。这里唯一的问题是:stl 容器在使用 OpenMP 时不仅仅是线程安全的吗?即,如果我想从多个线程在 std::list 中 push_back(),我仍然需要手动锁定该列表。
更新 2:我发现要 运行 并行部分中的单个操作,需要使用 #pragma omp single。那么,这个问题就结束了。
是的,这将创建一个并行区域,其中每个线程将在外循环上迭代 t
,并在线程之间拆分 i
循环迭代的工作。
请注意,#pragma omp for
的末尾有一个隐式屏障,因此您无需也编写显式屏障。可以使用 nowait
子句(即 #pragma omp for nowait
)删除此隐式障碍。