我正在学习关于这的OpenMP教程,我在第19页上遇到了这个练习。这是一个π计算算法,我不得不并行化:
static long num_steps = 100000;
double step;
void main ()
{
int i;
double x, pi
double sum = 0.0;
step = 1.0 / (double)num_steps;
for(i = 0; i < num_steps; i++)
{
x = (I + 0.5) * step;
sum = sum + 4.0 / (1.0 + x*x);
}
pi = step * sum;
}我不能用,到目前为止,#语用并行。我只能用:
#pragma omp parallel {}
omp_get_thread_num();
omp_set_num_threads(int);
omp_get_num_threads();我的实现如下所示:
#define NUM_STEPS 800
int main(int argc, char **argv)
{
int num_steps = NUM_STEPS;
int i;
double x;
double pi;
double step = 1.0 / (double)num_steps;
double sum[num_steps];
for(i = 0; i < num_steps; i++)
{
sum[i] = 0;
}
omp_set_num_threads(num_steps);
#pragma omp parallel
{
x = (omp_get_thread_num() + 0.5) * step;
sum[omp_get_thread_num()] += 4.0 / (1.0 + x * x);
}
double totalSum = 0;
for(i = 0; i < num_steps; i++)
{
totalSum += sum[i];
}
pi = step * totalSum;
printf("Pi: %.5f", pi);
}通过使用sum数组忽略这个问题(稍后解释它需要为sum值定义一个关键部分,其中包含#杂注omp关键或#杂注omp原子),上面的推进只适用于有限数量的线程(在我的示例中为800个线程),其中串行代码使用100000步。是否只有上述OpenMP命令才能实现这一目的,还是必须使用#语用omp并行处理,这一点在本教程中还没有提到?
非常感谢您的时间,我真的很想掌握C中使用OpenMP的并行化的概念。
发布于 2018-11-11 05:53:32
您将需要找到一种方法,使您的并行算法在某种程度上独立于线程数。
最简单的方法是做这样的事情:
int tid = omp_get_thread_num();
int n_threads = omp_get_num_threads();
for (int i = tid; i < num_steps; i += n_threads) {
// ...
}这样,无论线程数量多少,工作都会被分割到所有线程上。
如果有3个线程和9个步骤:
这是可行的,但如果每个线程都从某个共享数组访问数据,这并不理想。为了局部性的目的,线程访问附近的数据段会更好。
在这种情况下,您可以将步骤数除以线程数,并给每个线程一个连续的任务集,如下所示:
int tid = omp_get_thread_num();
int n_threads = omp_get_num_threads();
int steps_per_thread = num_steps / n_threads;
int start = tid * steps_per_thread;
int end = start + steps_per_thread;
for (int i = start; i < end; i++) {
// ...
}现在,执行9个步骤的3个线程如下所示:
这种方法实际上是使用#pragma omp for时最有可能发生的情况。在大多数情况下,编译器只是根据线程数来划分任务,并为每个线程分配一个节。
因此,给定一组2个线程和100次循环迭代,编译器可能会给线程0提供0-49的迭代,对线程1进行迭代( 50-99 )。
注意,如果迭代的次数没有被线程数平均除以,那么剩余的部分需要显式地处理。
https://stackoverflow.com/questions/53244922
复制相似问题