我是并行化的新手,希望我没有浪费大家的时间。我已经问过几个已经用过openMP的朋友,但是他们都帮不上忙。所以我想我的案例可能对其他人也很有趣,至少出于教育目的,我试着尽可能地把它记录下来。这是两个例子,其中一个100%取自蒂姆·马特森在youtube上的教程,另一个略为简化,但我想仍然是一种标准方法。在这两种情况下,对于很少的迭代,计算时间随线程数的变化而变化,但是对于非常大量的迭代,计算时间似乎收敛到相同的数字。这当然是错误的,因为我希望在很少的迭代中计算时间是相似的,并且真正优化了大量的迭代。
这里有两个例子,都是用 编译的 g++ -fopenmp main.cpp -o out
线程模型:posixgcc版本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 << "msn";
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 << "msn";
return 0;
}
现在,我认为在开始的时候,例2的速度会因为变量的减少而变慢,这会干扰并行化,但在例1中几乎没有任何共享。如果我做了一些非常愚蠢的事情,请告诉我,或者如果我可以指定问题的更多方面。谢谢大家。
正如gilles在评论中发布的那样,问题是我正在使用clock()测量时间,这将所有核心的tics加起来。
chrono::high_resolution_clock::now();
我得到了预期的加速。
对我来说,这个问题已经解决了,但也许我们可以把它作为一个例子,供未来像我这样的新手参考。如果一些mod不这样认为,该职位可以被取消。再次感谢您的帮助