并行与并行

这两者有什么区别?

[ A ]

#pragma omp parallel
{
#pragma omp for
for(int i = 1; i < 100; ++i)
{
...
}
}

[ B ]

#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
...
}
228511 次浏览

我不认为有什么不同,一个是捷径,另一个。尽管您的确切实现可能会以不同的方式处理它们。

组合的并行工作共享构造是 指定包含一个工作共享结构的并行结构 允许条款是条款的合并 允许并行和工作共享结构。

取自 http://www.openmp.org/mp-documents/OpenMP3.0-SummarySpec.pdf

OpenMP 的规格如下:

Https://openmp.org/specifications/

这些是等价的。

#pragma omp parallel产生一组线程,而 #pragma omp for在产生的线程之间划分循环迭代。您可以使用融合的 #pragma omp parallel for指令同时做这两件事。

当我在 g + + 4.7.0中使用 for 循环时,我看到了截然不同的运行时间 和使用

std::vector<double> x;
std::vector<double> y;
std::vector<double> prod;


for (int i = 0; i < 5000000; i++)
{
double r1 = ((double)rand() / double(RAND_MAX)) * 5;
double r2 = ((double)rand() / double(RAND_MAX)) * 5;
x.push_back(r1);
y.push_back(r2);
}


int sz = x.size();


#pragma omp parallel for


for (int i = 0; i< sz; i++)
prod[i] = x[i] * y[i];

序列码(没有 openmp)运行在79毫秒。 “并行”代码以29毫秒运行。 如果省略 for并使用 #pragma omp parallel,则运行时最多可以运行179ms, 它比串行代码慢。(机器的并发性为8)

代码链接到 libgomp

下面是使用分离的 parallelfor给你的例子。简而言之,它可以用于在多个线程中执行 for循环之前动态分配 OpenMP 线程私有数组。 在 parallel for的情况下不可能进行相同的初始化。

UPD: 在问句例子中,单个语用和两个语用没有区别。但是在实践中,您可以使用分离的并行和 for 指令来实现更多的线程感知行为。 一些代码例如:

#pragma omp parallel
{
double *data = (double*)malloc(...); // this data is thread private


#pragma omp for
for(1...100) // first parallelized cycle
{
}


#pragma omp single
{} // make some single thread processing


#pragma omp for // second parallelized cycle
for(1...100)
{
}


#pragma omp single
{} // make some single thread processing again


free(data); // free thread private data
}

尽管特定示例的两个版本是等价的,正如其他答案中已经提到的那样,但它们之间仍有一个小小的差异。第一个版本包含一个不必要的隐式障碍,在“ omp for”的末尾遇到。另一个隐式势垒位于平行区的末端。将“ nowait”添加到“ omp for”将使这两个代码相等,至少从 OpenMP 的角度来看是这样的。我之所以提到这一点,是因为 OpenMP 编译器可以为这两种情况生成略有不同的代码。

显然有很多答案,但这一个回答它非常好(与来源)

#pragma omp for只将循环的一部分委托给 不同的线程在 现在的团队。A 团队中是线程组 在程序开始时,团队只包括一个 单个成员: 运行程序的主线程

要创建一个新的线程团队,您需要指定并行 关键字。它可以在周围的上下文中指定:

#pragma omp parallel
{
#pragma omp for
for(int n = 0; n < 10; ++n)
printf(" %d", n);
}

以及:

什么是: 平行,为和一个团队

两者之间的区别, 与之平行的是:

团队是一组线程 在项目开始时,团队由 并行构造将当前线程拆分为 在下一个块/语句期间创建新的线程团队, 在此之后,团队合并成一个整体 For-loop 在当前团队的线程之间。

它不会创造 线程,它只是将工作分配给当前的线程 并行是同时执行两个命令的简写: 并行创建一个新的团队,并为分裂 团队来处理循环的不同部分。如果你的程序从来没有 包含一个并行结构,不存在多个线程; 启动并运行程序的主线程,如 非线程处理程序。

Https://bisqwit.iki.fi/story/howto/openmp/

只有的不同之处在于,第一代码调用 2隐式屏障,而 第二名代码只调用 1


使用现代官方 OpenMP 5.1标准作为参考的更详细的答案。

OpenMP 条款:

#pragma omp parallel

创建一个由 threads组成的 parallel region,其中每个线程将执行 平行区域平行区域封装的整个代码块。

OpenMP 5.1可以读出一个更为正式的描述:

当一个线程遇到 平行结构时,< strong > 一组线程是 创建 来执行并行区域(. .) 遇到并行结构的线程将成为主线程 新团队的线程,在此期间线程号为零 新团队中的所有线程,包括 主线程,执行该区域 期间团队中的线程数保持不变 那个平行区域。

答:

#pragma omp parallel for

创建一个 平行区域平行区域(如前所述) ,并使用默认的 chunk sizeschedule(即 一般来说 static)为该区域的 threads指定它封装的循环的迭代。然而,请记住,这些缺省值可能因 OpenMP标准的不同具体实现而有所不同。

OpenMP 5.1你可以读到一个更正式的描述:

工作共享循环构造指定一个或多个 中的线程将并行执行更多关联的循环 团队在他们的隐含任务上下文 分布在团队中已经存在的线程之间 执行工作共享循环区域所到的并行区域 绑定 .

此外,

并行循环构造是指定并行的快捷方式 包含有一个或多个关联的循环构造的 循环,没有其他语句。

或者非正式地说,#pragma omp parallel for是构造函数 #pragma omp parallel#pragma omp for的组合。

对于已经显示的两个版本,如果使用 chunk_size=1静电干扰 schedule,执行流程将导致类似下面的结果:

enter image description here

在代码方面,循环将被转换成类似于 逻辑上来说的东西:

for(int i=omp_get_thread_num(); i < n; i+=omp_get_num_threads())
{
//...
}

Omp _ get _ thread _ num ()在哪

Omp _ get _ thread _ num 例程返回线程号 调用线程的当前团队。

Omp _ get _ num _ thread ()

返回当前团队中的线程数 节返回1。

或者换句话说,for(int i = THREAD_ID; i < n; i += TOTAL_THREADS)THREAD_ID的范围从 0TOTAL_THREADS - 1,而 TOTAL_THREADS代表团队在平行区域上创建的线程总数。