增加线程数减少时间
Posted
技术标签:
【中文标题】增加线程数减少时间【英文标题】:increase number of threads decrease time 【发布时间】:2014-03-22 19:06:40 【问题描述】:我是 openmp 的新手。从openmp官方页面的教程开始 https://www.youtube.com/playlist?list=PLLX-Q6B8xqZ8n8bwjGdzBJ25X2utwnoEG
在该页面中有一个 hello world 程序通过近似积分来计算 pi。 我只是按照说明编写了下面的代码,但它的时间速度随着我增加更改 NUM_THREADS 的线程数而增加。在视频中,速度下降了。
我正在远程服务器上执行程序,该服务器有 64 个 CPU,每个 CPU 有 8 个内核。
#include <stdio.h>
#include <omp.h>
static long num_steps = 100000;
double step;
#define NUM_THREADS 2
int main()
int i, nthreads; double pi, sum[NUM_THREADS];
double start_t;
step = 1.0 / (double) num_steps;
omp_set_num_threads(NUM_THREADS);
start_t = omp_get_wtime();
#pragma omp parallel
int i, id, nthrds;
double x;
id = omp_get_thread_num();
nthrds = omp_get_num_threads();
if (id == 0) nthreads = nthrds;
for (i = id, sum[id] = 0.0; i < num_steps; i = i + nthrds)
x = (i + 0.5) * step;
sum[id] += 4.0 / (1.0 + x*x);
for (i = 0, pi = 0.0; i < nthreads; i++)
pi += sum[i] * step;
printf("%f\n", omp_get_wtime() - start_t);
【问题讨论】:
你的意思是8核8线程的远程服务器吗? 是的,8 核每核 8 个线程。 【参考方案1】:这是使用共享数组实现归约的一种不好的方法。 sum
的连续元素彼此太接近,因此驻留在同一缓存行中。在像 x86/x64 这样的缓存一致架构上,这会导致一个称为错误共享的问题。下面简单的修改就可以去掉它:
double sum[8*NUM_THREADS];
#pragma omp parallel
...
for (i = id, sum[id] = 0.0; i < num_steps; i = i + nthrds)
...
sum[8*id] += 4.0 / (1.0 + x*x);
for (i = 0, pi = 0.0; i < nthreads; i++)
pi += sum[8*i] * step;
仅显示相关更改。这个想法很简单:不是让线程访问sum
的连续元素,而是让它们访问每8 个元素。因此,可以保证线程不会共享与大多数现代 CPU 相同的高速缓存行,高速缓存行的长度为 64 字节,对应于 64 / sizeof(double)
= 8 个数组元素。
编辑:我的错误,应该首先观看视频。在显示运行代码的结果之后解释虚假共享。如果您的情况没有得到任何加速,那可能是因为较新的 CPU 代可以更好地处理错误共享。
【讨论】:
如果您要进行缩减,您应该让 OpenMP 通过使用“omp 并行”上的“缩减”子句为您完成。这样你就不必担心它的实现,只需让每台机器上的实现来做正确的事情,你就完全不需要全局数组了。reduction
子句稍后出现;)
我们的教学风格不同:-)。我会在讨论缓存问题之前解释归约,因为归约是一个高级(语义)概念,而缓存问题是低级的,将我们带入硬件的实现问题。对于那些回答“解释机器代码?”的人是“嗯,有一个叫做 Java 虚拟机的东西”,当他们的问题可以通过“让编译器为你做缩减”来解决时,你会因为跳跃到缓存争用而咬牙切齿。
我有什么资格与蒂姆·马特森的教学风格争论? :) 原来代码是故意这样写的,随后就引入了虚假共享。以上是关于增加线程数减少时间的主要内容,如果未能解决你的问题,请参考以下文章