为什么time.clock返回的经过时间比time.time多?

8

我在Ubuntu上使用time.clocktime.time计时了一段Python代码:

clock elapsed time: 8.770 s
time  elapsed time: 1.869 s

我理解time.time使用系统时间,而time.clock使用处理器时钟。当time.time给出的经过时间大于time.clock时,这对我来说是有道理的:处理器并非一直处于活动状态(例如,调用time.sleep)。
但是为什么/何时处理器时钟给出的经过时间会比系统时间多得如此之多呢?
附加说明
我进行了一个简单的测试,在标准映射、进程池映射和线程池映射中计算相同的函数。可以理解的是,进程池更快,线程池更慢。更有趣的是:在处理器池中,时钟计时小于时间计时,但在线程池中时钟计时却更长。
再次强调,我理解处理器池中时钟计时更短的原因:主进程不做太多事情,只等待池进程完成。但是为什么在线程池中时钟计时更长呢?有什么见解吗?
结果:
map
  time  1738.8
  clock 1739.6
mp pool
  time   580.1
  clock   15.9
thread pool
  time  3455.3
  clock 5378.9

代码:

from time import clock, sleep, time
from multiprocessing.pool import ThreadPool
from multiprocessing import Pool
import random

def f(i):
    x = [random.random() for j in range(100000)]
    return x[i]

def t(fn):
    t0, c0 = time(), clock()
    for i in range(10): fn(f,range(16))
    print '  time ', round(1000*(time()-t0),1)
    print '  clock', round(1000*(clock()-c0),1)

if __name__ == '__main__':
    print 'map'
    t(map)

    pool = Pool(8)
    print 'mp pool'
    t(pool.map)

    pool = ThreadPool(8)
    print 'thread pool'
    t(pool.map)

1
并行处理?你在运行8个核心吗? - dmg
我正在使用 Linux Mint。 - jmilloy
2
请参阅http://pymotw.com/2/time/,了解墙钟时间和处理器时钟时间之间的区别的详细解释。 - Lukas Graf
@LukasGraf 谢谢,但那只是解释了我已经知道的内容(并在上面总结了)。它没有解释处理器时钟时间如何大于墙上时间。此外,它建议使用时钟进行基准测试,但我理解这是不正确的(例如,timeit 在 Linux 上使用时间而不是时钟)。 - jmilloy
2
@LukasGraf:实际上,motw的解释是不正确的。请阅读time.clock()文档的当前版本——该函数的行为取决于平台,并且自Python 3.3以来已被弃用。即使在Linux上使用Python 2,也不应将其用于性能测量。使用timeit.default_timer,它可以为您提供最佳的计时器,无论Python版本如何,在您的系统上进行性能测量。 - jfs
显示剩余4条评论
1个回答

4

如果使用多个CPU执行,CPU时间可能会超过墙上时间。我在Python中没有特别看到过这种情况,但是我在C语言中使用多个线程的clock函数时确实看到了这种情况,而且很可能Python代码只是直接调用了这个C函数。

关于"为什么":你的思考方式有误。重要的是你的程序运行了多少个核心。如果一个核心在两秒的墙上时间内运行了一秒钟,那对你来说是有意义的,但是如果四个核心在同样的时间间隔内每个核心都运行了一秒钟,那么你就有了4秒的CPU时间和2秒的墙上时间。内核计算CPU时间以测量所有核心的时间。如果多个核心在同一秒内运行,则在该秒内花费了多个CPU秒。这是调度程序所关注的成本度量标准,很可能是clock所基于的指标。这可能不是你关心的度量标准,但这就是它的工作方式。


从经验上看,这似乎是事实。为什么? - jmilloy
std::clock 的文档只是简单地陈述了这一事实。 - b4hand
我正在尝试找出为什么。处理器时钟测量什么?它似乎衡量处理器处于活动状态的时间,但这不能完全准确,因为处理器不能比实际经过的时间更长时间处于活动状态(或者由于多线程在硬件级别上的工作方式,它可以吗?)。您提供的答案证实了我的经验,并指出这是记录在案的(即不是 bug)。但它没有解释为什么。 - jmilloy
7
在我的系统中,time.clock() 调用了 clock(3) C 函数,该函数是使用 clock_gettime(CLOCK_PROCESS_CPUTIME_ID) 实现的。后者表示与时钟关联的进程执行时间的量度,它不会计算子进程的 CPU 时间,似乎会为每个线程计算 CPU 时间("执行时间"),这就是为什么多核 CPU 上的多线程进程的时钟时间可能比墙壁时间大的原因。 - jfs
@jfs,你能把它发布为答案吗?这非常有用。 - max
@max 这不是一个答案。我的评论只是在当前回答的背景下提供了一些其他信息(例如)。 - jfs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接