我有两种测量指标的方案,如计算时间和并行加速(sequential_time / parallel_time)。
情景1:
顺序时间测量:
startTime=omp_get_wtime();
for loop computation
endTime=omp_get_wtime();
seq_time = endTime-startTime;
平行时间测量:
startTime = omp_get_wtime();
for loop computation (#pragma omp parallel for reduction (+:pi) private (i)
for (blah blah) {
computation;
}
endTime=omp_get_wtime();
paralleltime = endTime-startTime;
speedup = seq_time/paralleltime;
情景2:
顺序时间测量:
for loop{
startTime=omp_get_wtime();
computation;
endTime=omp_get_wtime();
seq_time += endTime-startTime;
}
平行时间测量:
for loop computation (#pragma omp parallel for reduction (+:pi, paralleltime) private (i,startTime,endTime)
for (blah blah) {
startTime=omp_get_wtime();
computation;
endTime=omp_get_wtime();
paralleltime = endTime-startTime;
}
speedup = seq_time/paralleltime;
我知道场景2不是最好的生产代码,但我认为它通过忽略openmp生成和管理(线程上下文切换)几个线程所涉及的开销来衡量实际的理论性能。所以它会给我们一个线性加速。但是场景1考虑了产生和管理线程所涉及的开销。
我怀疑是这样的: 在场景1中,我得到一个开始线性的加速,但随着我们进行更多次迭代而逐渐减少。在场景2中,无论迭代次数如何,我都会获得完整的线性加速。我被告知,实际上,无论迭代次数如何,场景1都会给我一个线性加速。但我认为它不会因为线程管理导致的高过载。有人可以向我解释为什么我错了吗?
谢谢!对于相当长的帖子感到抱歉。
答案 0 :(得分:5)
在很多情况下,方案2也不会给你线性加速 - 线程之间的错误共享(或者,就此而言,真正共享被修改的共享变量),内存带宽争用等。子线性加速通常是真实的,而不是测量神器。
更一般地说,一旦你到了将时间器置于 for循环中的那一点,你就会考虑使用比使用这样的定时器测量更精细的时序信息。您可能希望能够将线程管理开销从实际工作中解脱出来,原因有多种,但是您可以尝试通过向omp_get_wtime()
插入N个额外函数调用来实现这一点,以及算术和简化操作,所有这些操作都有不可忽视的开销。
如果你真的想要准确计算在computation;
行中花费多少时间,你真的想要使用像采样而不是手动仪器这样的东西(我们会谈谈区别{{3} })。使用here或gprof或scalasca(所有免费软件)或英特尔的VTune(商业软件包)将为您提供有关该线路上花费的时间的信息 - 通常甚至是线程 - 开销要低得多。
答案 1 :(得分:5)
首先,通过加速的定义,您应该使用方案1,其中包括并行开销。
在方案2中,paralleltime
的测量中的代码错误。为了满足方案2中的目标,您需要通过分配paralleltime
并通过int paralleltime[NUM_THREADS]
访问它们来获得每个线程omp_get_thread_num()
(请注意,此代码将具有错误共享,因此您最好用padding分配64字节结构。然后,测量每线程计算时间,最后采用最长的来计算不同类型的加速(我说的是一种并行性)。
不,即使是场景2,您也可能会看到亚线性加速,甚至可以获得超线性加速。潜在的原因(即排除并行开销)是:
compuation
中的工作负载长度在迭代时不同。这将是低速加速的最常见原因(但是,你说负载不平衡并非如此)。computation
需要大带宽和高工作集时,并行代码可能会受到带宽限制(尽管实际上很少见)和缓存冲突。此外,虚假共享是一个重要原因,但很容易避免它。也可以观察到超线性效应,因为使用多核可能有更多的缓存(即私有L1 / L2缓存)。在方案1中,它将包括并行库的开销:
我不认为您的代码(1级静态调度并行循环)由于线程管理而确实具有高并行开销,除非此代码每秒被调用数百万次。所以,可能是我在上面提到的其他原因。
请记住,有很多因素会决定加速;从固有的并行性(=负载不平衡和同步)到并行库的开销(例如,调度开销)。
答案 2 :(得分:2)
您想要准确测量什么?由并行性引起的开销是实际执行时间的一部分,因此恕我直言方案1更好。
此外,根据您的OpenMP指令,您正在减少某些数组。在方案1中,您考虑到了这一点。在方案2中,你不是。所以基本上,你测量的东西比方案1少。这可能对你的测量产生一些影响。
否则,Jonathan Dursi的回答非常好。
答案 3 :(得分:0)
OpenMP有多个选项可供选择如何在线程之间分配工作。这会影响测量方法1的线性度。您的测量方法2似乎没有用。你想要用什么来解决这个问题?如果您想了解单线程性能,请运行单个线程。如果您想要并行性能,则需要包含开销。