Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何实现高速、一致的采样?_Python - Fatal编程技术网

Python 如何实现高速、一致的采样?

Python 如何实现高速、一致的采样?,python,Python,需要考虑的应用类型是示波器或高速数据记录器。我有一个检索所需信息的函数,我只需要弄清楚如何一遍又一遍地调用它,非常快速,精度很高 时间是有限制的。sleep(),我不认为这是一种方式 import pygame import time pygame.init() TIMER_EVENT = pygame.USEREVENT+1 pygame.time.set_timer(TIMER_EVENT, 10) timer_count = 0 MAX_TIMER_COUNT = 1000 def

需要考虑的应用类型是示波器或高速数据记录器。我有一个检索所需信息的函数,我只需要弄清楚如何一遍又一遍地调用它,非常快速,精度很高

时间是有限制的。sleep(),我不认为这是一种方式

import pygame
import time

pygame.init()
TIMER_EVENT = pygame.USEREVENT+1

pygame.time.set_timer(TIMER_EVENT, 10)

timer_count = 0
MAX_TIMER_COUNT = 1000

def on_timer_event():
    global last_time
    global timer_count

    new_time = time.time()

    print new_time - last_time
    last_time = new_time

    timer_count += 1

    if timer_count > MAX_TIMER_COUNT:
        print last_time - initial_time
        pygame.event.post(pygame.event.Event(pygame.QUIT, {}))

initial_time = time.time()
last_time = initial_time
while True:
    event = pygame.event.wait()
    if event.type == TIMER_EVENT:
        on_timer_event()

    elif event.type == pygame.QUIT:
        break
我已经研究了内置的事件调度器,但我认为它不够精确,不能完全满足我的需要

这方面的要求是:

  • 高速采样。10毫秒是对它要求最多的时间
  • 高精度间隔。10ms时,10%的误差是可接受的(±1ms)
  • CPU使用率相当低,一些负载在10ms时是可以接受的,但在100ms及以上的时间间隔内应小于~5%。我知道这是主观的,我想我说的是,占用CPU是不可接受的
  • 理想情况下,计时器将以间隔时间初始化,然后在需要时启动。然后应以正确的间隔反复调用所需的函数,直到计时器停止
  • 它将(而不是必须)只在Windows计算机上运行

是否有满足这些要求的现有图书馆?我不想重新发明轮子,但如果必须的话,我可能会使用Windows多媒体计时器(winmm.dll)。有什么意见/建议吗?

编辑:在写了下面的内容之后,我倾向于为python事件调度器实现类似的测试。我不明白你为什么认为它不够准确

下面这样的东西在Linux下对我来说似乎工作得很好(我没有理由认为它在Windows下不起作用)。每隔10毫秒,将调用\u timer\u event()上的
,它将根据实时时钟打印自上次调用以来的时间。这显示了计时器的近似精度。最后,打印出总时间,以显示没有漂移

下面的代码似乎有一个问题,事件偶尔会以虚假的(短时间间隔)出现。我不知道这是为什么,但毫无疑问,通过一些游戏,你可以使它可靠。我认为这种方法是可行的

import pygame
import time

pygame.init()
TIMER_EVENT = pygame.USEREVENT+1

pygame.time.set_timer(TIMER_EVENT, 10)

timer_count = 0
MAX_TIMER_COUNT = 1000

def on_timer_event():
    global last_time
    global timer_count

    new_time = time.time()

    print new_time - last_time
    last_time = new_time

    timer_count += 1

    if timer_count > MAX_TIMER_COUNT:
        print last_time - initial_time
        pygame.event.post(pygame.event.Event(pygame.QUIT, {}))

initial_time = time.time()
last_time = initial_time
while True:
    event = pygame.event.wait()
    if event.type == TIMER_EVENT:
        on_timer_event()

    elif event.type == pygame.QUIT:
        break

我知道我回答我自己的问题已经晚了,但希望这能帮助别人

我为Windows多媒体计时器编写了一个包装器,纯粹是为了测试。它似乎工作得很好,但代码没有经过充分测试,也没有经过优化

mmtimer.py:

from ctypes import *
from ctypes.wintypes import UINT
from ctypes.wintypes import DWORD

timeproc = WINFUNCTYPE(None, c_uint, c_uint, DWORD, DWORD, DWORD)
timeSetEvent = windll.winmm.timeSetEvent
timeKillEvent = windll.winmm.timeKillEvent


class mmtimer:
    def Tick(self):
        self.tickFunc()

        if not self.periodic:
            self.stop()

    def CallBack(self, uID, uMsg, dwUser, dw1, dw2):
        if self.running:
            self.Tick()

    def __init__(self, interval, tickFunc, stopFunc=None, resolution=0, periodic=True):
        self.interval = UINT(interval)
        self.resolution = UINT(resolution)
        self.tickFunc = tickFunc
        self.stopFunc = stopFunc
        self.periodic = periodic
        self.id = None
        self.running = False
        self.calbckfn = timeproc(self.CallBack)

    def start(self, instant=False):
        if not self.running:
            self.running = True
            if instant:
                self.Tick()

            self.id = timeSetEvent(self.interval, self.resolution,
                                   self.calbckfn, c_ulong(0),
                                   c_uint(self.periodic))

    def stop(self):
        if self.running:
            timeKillEvent(self.id)
            self.running = False

            if self.stopFunc:
                self.stopFunc()
定期测试代码:

from mmtimer import mmtimer
import time

def tick():
    print("{0:.2f}".format(time.clock() * 1000))

t1 = mmtimer(10, tick)
time.clock()
t1.start(True)
time.sleep(0.1)
t1.stop()
from mmtimer import mmtimer
import time

def tick():
    print("{0:.2f}".format(time.clock() * 1000))

t1 = mmtimer(150, tick, periodic=False)
time.clock()
t1.start()
以毫秒为单位的输出:

0.00
10.40
20.15
29.91
39.68
50.43
60.19
69.96
79.72
90.46
100.23
150.17
一次性测试代码:

from mmtimer import mmtimer
import time

def tick():
    print("{0:.2f}".format(time.clock() * 1000))

t1 = mmtimer(10, tick)
time.clock()
t1.start(True)
time.sleep(0.1)
t1.stop()
from mmtimer import mmtimer
import time

def tick():
    print("{0:.2f}".format(time.clock() * 1000))

t1 = mmtimer(150, tick, periodic=False)
time.clock()
t1.start()
以毫秒为单位的输出:

0.00
10.40
20.15
29.91
39.68
50.43
60.19
69.96
79.72
90.46
100.23
150.17
从结果中可以看出,它非常准确。然而,这只是使用了
time.clock()
,所以要用一小撮盐


在使用10ms周期计时器进行长时间测试期间,在我的旧双代码3GHz机器上,CPU使用率约为3%或更少。机器在空闲时似乎也会使用它,所以我想说额外的CPU使用量是最小的。

对于DLL,cython是一个不错的选择。忽略所有说使用ctypes;)的傻瓜您可以尝试(pygame是在成熟的基础上构建的)。我自己没有直接的经验,所以这是我建议的限度。大多数gui库都有某种计时器,听起来它们可以完成这项工作。实现(1)和维护(2)要比引入一些外部平台依赖关系更快,这些外部平台依赖关系可以在您的控制范围内完成相同的最小工作,而不会产生开销(3)。对我来说,这三个优点本身就足够了。“没有开销”可能很难找到,我也在猜测。@JonasByström:我现在也开始倾向于这个。回到家后,我会试试,看看我的状态如何。由于一些糟糕的遗留原因,Windows对所有应用程序的默认分辨率为55毫秒。这可以使用winmm.dll更改,正如@gjwebber.Oh所暗示的,这就是我不知道的原因。感谢@JonasByström提供的有用信息!我将把答案留给那些没有使用遗留操作系统的人。我编辑了你的代码,使用time.clock()而不是time.time(),并在我的机器上运行了测试。一般来说,结果很好,但非常不稳定,我无法找出原因:结果低于5ms:70,最小值:0.00600890207716,最大值:21.4719634694,平均值:10。0007414478@gjwebber值得注意的是,在Unix上,time.clock()是cpu时间,因此在这种情况下没有多大帮助。但在Windows上,它似乎确实是正确的使用方式。您的差异似乎比我在Linux上体验到的要大得多。我认为乔纳斯的观点可以解释为什么,尽管我不是一个真正的Windows用户。@HenryGomersall:我现在在Windows机器上,这就是我编辑的原因。平均值是完美的,但两边的变化必须相当大,而且经常如此。接下来我将尝试cython和winmm.dll,看看进展如何。谢谢你的帮助