C++ 如何在并行体系结构中执行可靠的性能测试?

C++ 如何在并行体系结构中执行可靠的性能测试?,c++,parallel-processing,C++,Parallel Processing,我正在计算几何领域开发数据结构和算法。对我来说,能够可靠地比较两种算法的运行时间是非常重要的 问题是,当我运行一个算法,它运行了30分钟,我不能说这30分钟是用来执行算法,而不是播放MP3 我有一个英特尔®内核™ i7-2600 CPU@3.40GHz×8处理器运行Ubuntu 13.04的计算机。我所有的程序都是用C++编写的,只使用C或C++编写的库。 这是否意味着我可以安全地并行运行6个实验,而操作系统将使用另外2个用于自己的业务 我应该将实验作为一个程序的6个线程运行,还是制作6个不同的

我正在计算几何领域开发数据结构和算法。对我来说,能够可靠地比较两种算法的运行时间是非常重要的

问题是,当我运行一个算法,它运行了30分钟,我不能说这30分钟是用来执行算法,而不是播放MP3

我有一个英特尔®内核™ i7-2600 CPU@3.40GHz×8处理器运行Ubuntu 13.04的计算机。我所有的程序都是用C++编写的,只使用C或C++编写的库。 这是否意味着我可以安全地并行运行6个实验,而操作系统将使用另外2个用于自己的业务

我应该将实验作为一个程序的6个线程运行,还是制作6个不同的可执行文件并运行它们

这两种方法的区别是什么


如果您希望获得一致的结果,那么一次运行一个基准测试将提高这种可能性,因为不同的任务更有可能:

从一个CPU移动到另一个CPU,从而降低加载到缓存中的内容的意义。 造成内存带宽和缓存压力,从而干扰其他进程。 如果你在播放MP3、下载大片长度电影等的同时运行基准测试,那么你就不知道这是否真的干扰了你的CPU密集型任务,或者它对你的CPU密集型任务的干扰程度有多大——你可以,或许可以从另一个角度来判断音乐是否开始变得不稳定,或者下载超时;与并行运行多个任务一样,缓存和从处理器到处理器核心的移动将是最重要的影响

你可能会发现,如果你运行一组所有东西都打开的基准测试,而运行另一组所有东西都关闭的基准测试,这没有什么区别。但你也可能会发现,这确实会带来不同

这同样适用于运行一个或多个基准测试。尝试并行运行6,并比较运行时每个基准本身所花费的时间与不运行其他基准的时间

你只有通过比较不同的案例才能知道这一点

如果没有区别,您可以继续播放音乐、下载最新的大片等,同时进行基准测试,因为您知道,0.01%的差异对应用程序的整体性能并不重要

根据经验,我发现,如果你在背景中运行一组其他灯光效果,通常不会产生太大的影响,但会增加从一个运行到另一个运行的变化量。同样,如果基准测试运行了半个小时,这可能无关紧要——毕竟,从一次运行到另一次运行,您可能会在该运行时有足够的变化,仅仅是CPU和操作系统中的一般变化,纯粹是由于每次发生的事情不完全相同的因素,这不会产生足够的差异


如果您正在进行小的优化,例如切换编译器选项,使结果差异为0.5%,但运行之间的差异为1%,那么您需要运行多个运行以显示实际差异,并且来自其他进程的干扰越大,您就越有可能无法测量小的更改。有时,许多小的更改一起会产生显著的差异,例如,如果您移动函数F1以允许其内联,然后对函数F2执行相同的操作,则它们加在一起相当于1%的改进,但单独而言,这是无法测量的,因为它隐藏在噪声中。噪音越大,你就越有可能错过一些微小但最终有益的改变

如果您希望获得一致的结果,一次运行一个基准测试将提高这种可能性,因为不同的任务更有可能:

从一个CPU移动到另一个CPU,从而降低加载到缓存中的内容的意义。 造成内存带宽和缓存压力,从而干扰其他进程。 如果你在播放MP3、下载大片长度电影等的同时运行基准测试,那么你就不知道这是否真的干扰了你的CPU密集型任务,或者它对你的CPU密集型任务的干扰程度有多大——你可以,或许可以从另一个角度来判断音乐是否开始变得不稳定,或者下载超时;与并行运行多个任务一样,缓存和从处理器到处理器核心的移动将是最重要的影响

你可能会发现,如果你运行一组所有东西都打开的基准测试,而运行另一组所有东西都关闭的基准测试,这没有什么区别。但你也可能会发现,这确实会带来不同

这同样适用于运行一个或多个基准测试。尝试并行运行6,并比较运行时每个基准本身所花费的时间与不运行其他基准的时间

只有通过比较不同的 案例

如果没有区别,您可以继续播放音乐、下载最新的大片等,同时进行基准测试,因为您知道,0.01%的差异对应用程序的整体性能并不重要

根据经验,我发现,如果你在背景中运行一组其他灯光效果,通常不会产生太大的影响,但会增加从一个运行到另一个运行的变化量。同样,如果基准测试运行了半个小时,这可能无关紧要——毕竟,从一次运行到另一次运行,您可能会在该运行时有足够的变化,仅仅是CPU和操作系统中的一般变化,纯粹是由于每次发生的事情不完全相同的因素,这不会产生足够的差异


如果您正在进行小的优化,例如切换编译器选项,使结果差异为0.5%,但运行之间的差异为1%,那么您需要运行多个运行以显示实际差异,并且来自其他进程的干扰越大,您就越有可能无法测量小的更改。有时,许多小的更改一起会产生显著的差异,例如,如果您移动函数F1以允许其内联,然后对函数F2执行相同的操作,则它们加在一起相当于1%的改进,但单独而言,这是无法测量的,因为它隐藏在噪声中。噪音越大,你就越有可能错过一些微小但最终有益的改变

首先:英特尔i7-2600有4个真正的内核,但每个内核可以并行运行两个线程。通过操作系统调度程序的抢占,这种超线程比传统线程更快。因为执行可以在另一个线程上继续,如果一个线程必须等待很短的时间,比如在缓存未命中后从主内存读取值时,超线程往往会增加一点吞吐量。因此,在超线程内核上运行的两个进程的综合性能通常比在同一内核上运行的单个进程的性能高10%到20%。但是,在高速缓存压力较高的情况下,综合性能可能会更差

但是,对于您的性能计时需求来说,更重要的是:如果一个核心上的两个线程的综合性能为120%,这意味着单线程性能将下降到60%

据我所知,linux内核调度器知道超线程,因此如果第一个线程正在做繁重的工作,并且仍然有可用的内核,它将尝试使每个内核上的第二个线程保持空闲。所以,如果您只并行启动3个计时进程,并为您的桌面保留一个内核,并且不做很多诸如编译等辅助工作,那么您应该获得相当一致的计时数据!如果启动4个进程,请确保桌面确实处于空闲状态。如果启动5个或更多进程,则可能会由于超线程而导致计时结果不一致


如果使用shell上的时间来计时命令,则报告的用户和系统时间往往比总时间更准确。这是因为操作系统只计算用户时间和系统时间,进程实际上分别在userland或系统中运行。如果您的代码没有做太多的I/O,系统时间应该很短,用户时间应该接近总运行时间。

首先:Intel i7-2600有4个真正的内核,但每个内核可以并行运行两个线程。通过操作系统调度程序的抢占,这种超线程比传统线程更快。因为执行可以在另一个线程上继续,如果一个线程必须等待很短的时间,比如在缓存未命中后从主内存读取值时,超线程往往会增加一点吞吐量。因此,在超线程内核上运行的两个进程的综合性能通常比在同一内核上运行的单个进程的性能高10%到20%。但是,在高速缓存压力较高的情况下,综合性能可能会更差

但是,对于您的性能计时需求来说,更重要的是:如果一个核心上的两个线程的综合性能为120%,这意味着单线程性能将下降到60%

据我所知,linux内核调度器知道超线程,因此如果第一个线程正在做繁重的工作,并且仍然有可用的内核,它将尝试使每个内核上的第二个线程保持空闲。所以,如果您只并行启动3个计时进程,并为您的桌面保留一个内核,并且不做很多诸如编译等辅助工作,那么您应该获得相当一致的计时数据!如果启动4个进程,请确保桌面确实处于空闲状态。如果启动5个或更多进程,则可能会由于超线程而导致计时结果不一致

如果使用shell上的时间来计时命令,则报告的用户和系统时间往往比总时间更准确。这是因为操作系统只计算用户时间和系统时间,进程实际上是运行的
分别在userland或系统中使用。如果你的代码没有做太多的I/O,系统时间应该很短,用户时间应该接近总运行时间。

你一次运行一个,在后台没有其他东西。你现在如何测量时间?另外,你可能想看看命令。@Joachim我制作了6个单独的可执行文件,然后一次运行它们。我不时检查系统监视器工具,以检查是否至少有一个处理器的负载低于100%。@MartinDrozdik不,它们不一样。1您的处理器只有4个内核,而不是8个。两个线程共享同一个内核。2所有内核共享相同的内存带宽。3它们都共享相同的电源管理。您可以一次运行一个,而不在后台运行其他程序。现在如何测量时间?另外,您可能需要查看该命令。@Joachim我创建了6个单独的可执行程序,并同时运行它们。我不时检查系统监视器工具,以检查是否至少有一个处理器的负载低于100%。@MartinDrozdik不,它们不一样。1您的处理器只有4个内核,而不是8个。两个线程共享同一个内核。2所有内核共享相同的内存带宽。3它们都使用相同的电源管理。感谢您详尽的回答!谢谢你详尽的回答!