在C#里面如何尽量精确的比较两个算法的性能?

tczyp 2006-10-21 07:35:03
为了对两个算法进行尽可能精确的时间上的比较,C#里面所提供的最精确的时间计算的函数是什么呢?如果时间并不那么精确,那么有没有记录CPU时钟滴嗒的函数?另外,因为windows是一个多任务系统,有没有办法让机器在某段时间里面只运行某段程序?还有就是C#运行时还要进行编译,这会不会影响了对算法用时的度量?
...全文
287 10 打赏 收藏 举报
写回复
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
tczyp 2006-11-05
  • 打赏
  • 举报
回复
上面朋友说的不太准确,如果采取循环1000次然后计算平均数的话,对记时器的精度要求只要秒级别的就相当于执行一次计时使用毫秒级别精度的计时器。
six_six_2005 2006-11-03
  • 打赏
  • 举报
回复
难点不是如何选择你说的这两种计算时间的办法.而是该选择哪一种定时器才能够精确地计量时间,以达到所要求的精度,并不是每一种定时器都可以满足精度要求.
"浮点运算"作为测量单位,我没有接触过.有没有相关资料?
tczyp 2006-11-03
  • 打赏
  • 举报
回复
现在我觉得有两种计算时间的办法,一种是使待测任务运行多次后得到总时间,然后除以运行的次数得到每一次使用的时间。而另外一种办法是记录待测任务每次运行的时间,然后求平均。后者比较易于操作,但是不知道准确性有没有前者高。如果我测量的任务运行时间大概是1ms到10ms那种测量方法比较合适。

另外,我看到有些测量标准是以“浮点运算”作为测量单位的,如果要以这个作为测量单位,C#里面有没有办法较容易实现?
six_six_2005 2006-11-02
  • 打赏
  • 举报
回复
托管类的以下两个属性似乎可以用作计时器,但是不适用于评测较小的时间段.(对于1/10秒以上它们合适)
1.System.Environment.TickCount 精度1ms
2.System.DateTime.Now.Ticks 精度100ns=0.1ms
需要一个高精度的计时器,以评估微小的时间间隔.不过 .NET Framework类库没有提供这样的计时器.所以使用非托管代码和一个本机的API方法QueryPerformanceCounter.此计数器以一个特定频率进行增量(一个时间片),频率本身并不确定,因为它取决于您的硬件,所以需要调用另一个方法QueryPerformanceFrequency来获取频率值.


例子:功能描述:计算一个循环所花费的时间
using System;
using System.Runtime.InteropServices;

namespace Demo
{
/// <summary>
/// 测试类。
/// </summary>
public class MainEntryPoint
{
/// <summary>
/// 主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
int quantity = 0;
IntervalTimer timer = new IntervalTimer();
//多次测试,以使信息准确
for(int numTests = 0; numTests < 7; numTests++)
{
//测试启动和结束计时器所需要的额外时间开销
timer.Start();
timer.Stop();
Console.WriteLine("Just Starting and stopping timer:");
Console.WriteLine(" "+timer.ToString());
Console.WriteLine("----------------------------------------");

//执行实际的测试
timer.Start();
for(int i =0; i < 1000; i++)
quantity += i;//防止被JIT优化
timer.Stop();
//输出结果
Console.WriteLine("Counting to 1000:");
Console.WriteLine(" "+timer.ToString());
Console.WriteLine("##########################################");
}
Console.WriteLine("\nquantity is "+quantity);
}
}

/// <summary>
/// 封装的计时器类
/// </summary>
public class IntervalTimer
{
[DllImport("kernel32.dll")]
static extern private int QueryPerformanceCounter(out long count);
[DllImport("kernel32.dll")]
static extern private int QueryPerformanceFrequency(out long count);

//表示计时器是否已经启动或者停止的枚举
public enum TimerState{NotStarted,Stopped,Started}

private TimerState state;
private long ticksAtStart; //tick count when Start() called
private long intervalTicks; //no. of ticks elapsed until Stop() called
private static long frequency; //存储计时器频率的信息,每秒包含的时间片数量
private static long decimalPlaces;//在输出计时信息时使用,存储精度的值
private static string formatString; //存储格式化字符串
private static bool initialized=false;

private static long CurrentTicks
{
get
{
long t;
QueryPerformanceCounter(out t);
return t;
}
}
public IntervalTimer()
{
if(!initialized)
{
QueryPerformanceFrequency(out frequency);//确定频率
decimalPlaces = (int)Math.Log10(frequency); 
formatString = String.Format("Interval:{{0:F{0}}} seconds ({{1}} ticks)",
decimalPlaces);
initialized = true;
}
state = TimerState.NotStarted;
}

public void Start()
{
state = TimerState.Started;
ticksAtStart = CurrentTicks;
}

public void Stop()
{
intervalTicks = CurrentTicks - ticksAtStart;
state = TimerState.Stopped;
}

// 计算调用Start()和Stop()分别需要耗费多少时间片  
public float GetSeconds()
{
if(state != TimerState.Stopped)
throw new TimerNotStoppedException();
return (float)intervalTicks/ (float)frequency;
}

public override string ToString()
{
if(state != TimerState.Stopped)
return "Interval timer, state:"+ state.ToString();
return String.Format(formatString, GetSeconds(),intervalTicks);
}
}

//自定义的异常
public class TimerNotStoppedException:ApplicationException
{
public TimerNotStoppedException()
:base("Timer is either still running or has not been started")
{
}
}
}
Nara 2006-10-22
  • 打赏
  • 举报
回复
这主要看你对于精度的要求了,一般10ms到1s的时间间隔用简单的方法很难准确得到。因为一般系统提供的基本计时方式,就是基于timer(低频中断计时器)和counter(时钟周期计数器)在这个范围都工作的不是很好。如你有兴趣,可以看看《Computer Systems A Programmer's Perspective》Chapter 9,很有帮助
six_six_2005 2006-10-21
  • 打赏
  • 举报
回复
运行命令perfmon.exe可以对性能监视器有个直观的认识.
可以监视系统资源,如CPU,内存,网络UDP包数量等等.
其主要用于没有界面的开发,即"WindowsServices",因为服务可能没有用户交互式响应. 主要使用日志进行记录.
winner2050 2006-10-21
  • 打赏
  • 举报
回复
运行次数多点就能看出差异了。
tczyp 2006-10-21
  • 打赏
  • 举报
回复
非常想知道什么是性能记数器?
six_six_2005 2006-10-21
  • 打赏
  • 举报
回复
可以考虑一下使用"性能计数器",可以记录嘀嗒.
Professional C#里有介绍.
aafshzj 2006-10-21
  • 打赏
  • 举报
回复
记得小学的时候如何计算一张纸币的厚度吗?

多run一些次数,单次的精度对你的算法的总体精度就不重要了。考虑到操作系统的时间分片特点,片面追求单次计算时间精度是没有意义的。

至于JIT对算法肯定有一点影响,可使所有的算法都受到处理器、硬件的影响。因为很多算法一旦脱离了物理设备是根本没实际意义的。所以,重要的是算法基于同样的设备基于benchmark的比较。JIT对算法是公平的,应该不是问题。
相关推荐
发帖
C#

10.8w+

社区成员

.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
帖子事件
创建了帖子
2006-10-21 07:35
社区公告

让您成为最强悍的C#开发者