我正在阅读Peter S. Pacheco 对并行编程的介绍.在5.6.2节中,它提供了一个关于减少fork/join开销的有趣讨论.考虑奇偶换位排序算法:
for(phase=0; phase < n; phase++){
if(phase is even){
# pragma omp parallel for default(none) shared(n) private(i)
for(i=1; i<n; i+=2){//meat}
}
else{
# pragma omp parallel for default(none) shared(n) private(i)
for(i=1; i<n-1; i+=2){//meat}
}
}
Run Code Online (Sandbox Code Playgroud)
作者认为上面的代码有一些高的fork/join开销.因为线程在外循环的每次迭代中分叉并连接.因此,他提出以下版本:
# pragma omp parallel default(none) shared(n) private(i, phase)
for(phase=0; phase < n; phase++){
if(phase is even){
# pragma omp for
for(i=1; i<n; i+=2){//meat}
}
else{
# pragma omp for
for(i=1; i<n-1; i+=2){//meat}
}
}
Run Code Online (Sandbox Code Playgroud)
根据作者的说法,第二个版本在外部循环开始之前分叉线程,并为每次迭代重用线程,从而产生更好的性能.
但是,我怀疑第二个版本的正确性.在我的理解中,#pragma omp parallel指令启动一组线程并让线程并行执行以下结构化块.在这种情况下,结构化块应该是整个外部for循环 …
众所周知,在 C++ 中我们可以有像 int 这样的非类型模板参数:
template <class T, int size>
void f(){...}
Run Code Online (Sandbox Code Playgroud)
我想知道它与将参数传递给函数的普通方式有何不同:
template <class T>
void f(int size) {...}
Run Code Online (Sandbox Code Playgroud)
我认为一个区别是模板size在编译时评估并在实例化模板时替换为文字。因此,我怀疑(如果我错了,请纠正我)每个不同的size值都会导致创建新的二进制代码(“.text”),这似乎是一种开销。
谁能告诉我们什么时候这是必要且值得的?