我是并行化的新手,我希望我不浪费任何人的时间。我已经问了一些已经使用过openMP的朋友,但他们无法帮助我。所以我猜我的情况对其他人来说也很有意思,至少在教育方面是这样,我试着把它记录得尽可能好。这是两个例子,其中一个100%来自Tim Mattson在youtube上的教程,另一个以某种方式简化,但我认为仍然是一种标准方法。在这两种情况下,计算时间与几次迭代的线程数量成比例,但是对于非常大量的迭代,计算时间似乎收敛到相同的数量。这当然是错误的,因为我希望计算时间在几次迭代中是相似的,并且真正针对大量迭代进行了优化。
这里有两个例子,都是用
编译的 g++ -fopenmp main.cpp -o out
线程模型:posix gcc版本4.8.4(Ubuntu 4.8.4-2ubuntu1~14.04),在Ubuntu 14.04上 并使用以下标题:
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <iostream>
using namespace std;
#define NUMBER_OF_THREADS 2
static long num_steps = 1000000000;
现在,我正在使用的计算机上的内核数量是8(intel i7),所以在2到4之间的任意数量的线程我都希望在计算时间方面带来一些很大的优势。
示例1:
int main() {
omp_set_num_threads(NUMBER_OF_THREADS);
double step = 1.0/(double) num_steps, pi=0.0;
auto begin = chrono::high_resolution_clock::now();
#pragma omp parallel
{
int i, ID, nthrds;
double x, sum = 0;
ID = omp_get_thread_num();
nthrds = omp_get_num_threads();
for (i=ID; i<num_steps; i=i+nthrds) {
x = (i+0.5)*step;
sum = sum + 4.0/(1.0+x*x);
}
#pragma omp critical
pi += step*sum;
}
auto end = chrono::high_resolution_clock::now();
cout << chrono::duration_cast<chrono::nanoseconds>(end-begin).count()/1e6 << "ms\n";
return 0;
}
示例2:
int main() {
omp_set_num_threads(NUMBER_OF_THREADS);
double pi=0, sum = 0;
const double step = 1.0/(double) num_steps;
auto begin = chrono::high_resolution_clock::now();
// #pragma omp parallel
{
#pragma omp parallel for reduction(+:sum)
for (int i=0; i<num_steps; i++) {
double x = (i+0.5)*step;
sum += 4.0/(1.0+x*x);
}
}
pi += step*sum;
auto end = std::chrono::high_resolution_clock::now();
cout << chrono::duration_cast<chrono::nanoseconds>(end-begin).count()/1e6 << "ms\n";
return 0;
}
现在,我开始认为示例2因变量的减少而减慢,这会扰乱并行化,但在示例1中几乎没有任何共享。如果我正在做一些非常愚蠢的事情,或者我可以指出问题的更多方面,请告诉我。谢谢大家。
答案 0 :(得分:5)
正如gilles在评论中所发表的那样,问题在于我用clock()测量时间,这加起来核心的所有抽搐。 与
chrono::high_resolution_clock::now();
我得到了预期的加速。
对我来说,这个问题已被清除,但也许我们可以将此作为未来像我这样的新手的例子。如果某个mod认为其他人可以消除这个帖子。 再次感谢您的帮助