由于我在(抢占式)多任务,多核环境中运行多线程程序的性能评估测试,因此可以定期更换该进程。我想计算延迟,即只计算进程处于活动状态的持续时间。这将允许我推断性能在非多任务环境中的表现,即,只有一个程序正在运行(大多数时间),或者在不同的工作负载上。
通常会测量两种时间:
我相信我需要的是单个线程的完成时间,这可能与任何线程由于线程之间的任务依赖性结构所使用的最大CPU时间不同。例如,在具有2个线程的进程中,线程1在运行时的前三分之二(CPU时间t)中负载很重,而线程2在该进程的后三分之二中加载(同样,对于CPU时间t)。在这种情况下:
此外,多线程本身带来了不确定性。这个问题可能需要多次运行测试并总结结果。
此外,延迟还取决于操作系统如何调度线程;如果进程的某些线程等待CPU而其他线程运行,则事情会变得更复杂。但是让我们忘记这一点。
有没有一种有效的方法来计算/估算这个完工时间?要提供代码示例,请使用任何编程语言,但最好使用Linux上的C或C ++。
PS:我理解这个makepan的定义与调度问题的定义不同。调度问题中使用的定义类似于挂钟时间。
答案 0 :(得分:3)
我编写了一个多线程应用程序,需要X秒才能在我的K-core机器上执行。
如何估算程序在单核计算机上运行需要多长时间?
显而易见的解决方案是让计算机具有一个核心,然后运行您的应用程序,并根据需要使用挂钟时间和/或CPU时间。
...哦,等等,你的电脑已经有一个核心(它还有一些核心,但我们不需要使用它们)。
如何做到这一点取决于操作系统,但我从谷歌找到的第一批结果之一解释了Windows XP和Vista的一些方法。
http://masolution.blogspot.com/2008/01/how-to-use-only-one-core-of-multi-core.html
接下来你可以:
通过分析估计这一点需要了解您的程序,并行方法等等。
作为一个简单的例子,假设我编写了一个多线程程序,它计算pi的第十亿个十进制数和e的第十亿个十进制数。
我的代码如下:
public static int main()
{
Task t1 = new Task( calculatePiDigit );
Task t2 = new Task( calculateEDigit );
t1.Start();
t2.Start();
Task.waitall( t1, t2 );
}
之前发生的图表如下:
显然这些是独立的。
在这种情况下
当任务不是独立的时,您将无法将各个时间加在一起。
在下一个示例中,我创建了一个多线程应用程序:获取10个图像,将它们转换为灰度,然后运行线检测算法。由于某些外部原因,不允许每个图像不按顺序处理。因此,我创建了一个管道模式。
我的代码看起来像这样:
ConcurrentQueue<Image> originalImages = new ConcurrentQueue<Image>();
ConcurrentQueue<Image> grayscaledImages = new ConcurrentQueue<Image>();
ConcurrentQueue<Image> completedImages = new ConcurrentQueue<Image>();
public static int main()
{
PipeLineStage p1 = new PipeLineStage(originalImages, grayScale, grayscaledImages);
PipeLineStage p2 = new PipeLineStage(grayscaledImages, lineDetect, completedImages);
p1.Start();
p2.Start();
originalImages.add( image1 );
originalImages.add( image2 );
//...
originalImages.add( image10 );
originalImages.add( CancellationToken );
Task.WaitAll( p1, p2 );
}
以数据为中心发生在图表之前:
如果此程序设计为开始的顺序程序,出于缓存原因,在移动到下一个图像之前,一次取一个图像并将它们移动到完成会更有效。
无论如何,我们知道GrayScale()将被调用10次而LineDetection()将被调用10次,所以我们可以单独计时,然后将它们乘以10。
但是推送/弹出/轮询ConcurrentQueues的成本呢?
假设图像很大,那个时间可以忽略不计。
如果有数百万个小图像,每个阶段都有许多消费者,那么当程序按顺序运行时,您可能会发现等待锁,互斥锁等的开销非常小(假设其数量为在关键部分中执行的工作很小,例如在并发队列中。
看看这个问题:
How to estimate the thread context switching overhead?
基本上,您将在多核环境和单核环境中进行上下文切换。
执行上下文切换的开销非常小,但每秒也会发生很多次。
危险在于上下文切换之间缓存完全中断。
例如,理想情况下:
然而,这可能发生:
在运行它的同一环境中没有什么能比计时更快。
接下来最好是尽可能地模拟这个环境。
无论如何,了解您的程序设计应该可以让您了解在新环境中会发生什么。