为什么我的C#计算时间可能是非确定性的?

时间:2011-07-13 12:42:28

标签: c# .net

我正在运行一个搜索算法,该算法在一开始就用单个种子提供。从这一点开始,我希望算法能够以确定的方式运行,而这在很大程度上也是如此。通过查看第10,000步,20,000步并看到它们是相同的,我可以在很大程度上验证这一点。我看到的不同之处是用于到达同一位置的线程处理器时间的长度(采用相同的路径)。我正在测量线程时间 ProcessThread.TotalProcessorTime。

为了量化这个,我已经为你做了一些测试。我改变了运行时间并测量了在这段时间内评估的解决方案的数量


    30s         60s          120s        120s
473,962     948,800     1,890,668   1,961,532
477,287     954,335     1,888,955   1,936,974
473,441     953,049     1,895,727   1,960,875
475,606     953,576     1,905,271   1,941,511
473,283     951,390     1,946,729   1,949,231
474,846     954,307     1,840,893   1,939,160
475,052     952,949     1,848,938   1,934,243
476,797     957,179     1,945,426   1,951,542

475,034     476,599       473,831     486,721
  1,478       2,426        23,922      11,108

我每次重复测试8次。底部两行显示在30秒期间评估的平均解决方案,然后是标准偏差。我重复了120s测试,因为标准偏差第一次如此之高,第二次低得多。

如果我的算法做了同样的工作,那么什么可能导致相同的工作花费不同的时间?什么是随机元素?

澄清几点:

  1. 我说的是线程处理器时间而不是时钟时间
  2. 该算法在单个线程上运行,没有与其他线程的明确交互
  3. 此环境是Windows XP .Net C#双处理器
  4. 这是一个控制台应用程序
  5. 算法使用处理器和内存,只有在完成后才会将结果打印到屏幕上。
  6. 最好的问候

5 个答案:

答案 0 :(得分:5)

优化,内存管理(GC,分配,分页等)和及时编译。

答案 1 :(得分:4)

在处理器级别上,缓存未命中和错误的分支预测都会影响从一次运行到另一次运行所需的处理器时间。在框架级别,JITing和GC也可以影响它。后者比前者更容易观察到。

答案 2 :(得分:2)

您的算法可能是确定性的,但绝对没有环境和运行时元素:

  • 代码在需要分配内存的运行时上运行,从您的角度来看是非确定性的。
  • 从您的角度来看,运行时有一个垃圾收集器,它在不确定的时间内运行非确定性时段。
  • 操作系统实时不是软件或硬件,因此处理器管理会影响时序。

总而言之,不要指望非确定性系统中的确定性行为。 Windows CE支持硬实时,但您仍然需要使用.NET以外的东西。

请记住,“确定性”在某种意义上说:“这段代码每次运行时都会完全 20毫秒。你没有希望通过运行时实现这一点非确定性的操作系统上的非确定性。

操作系统意义上的确定性通常不如“完全”严格,更像是:“我可以保证我在X内回复,否则我会错误”。在这一点上,软实时和硬实时分别越来越灵活。

答案 3 :(得分:1)

处理器时间是共享时间,因此计算机上发生的任何其他活动都会影响性能。

我有所纠正。

答案 4 :(得分:1)

您的算法使用哪些资源?是否有其他进程使用相同的资源?这包括CPU,内存,IO(页面文件)。其他过程会对算法的性能产生影响。

时间有什么不同? 1%? 10%?