Python 3.x 切片数据的改进?

Python 3.x 切片数据的改进?,python-3.x,slice,Python 3.x,Slice,背景 我有一个返回ascii流的硬件&用户可以选择 时间步数 频道数量 一个数据包=[地址][MSB][LSB][校验和] 一个时间戳=[时间分组][CH1分组][CH2分组][CH3分组][CH4分组][CH5分组][CH6分组][CH7分组] 下面是一些精简的代码,我使用这些代码创建7个以上的时间数组,然后通过matplotlib进行绘图。问题是,这需要相当长的时间来处理。。。30000个样本和7个通道2.7秒。我用过cython,我把这个块编译成一个C扩展,速度并没有那么快 完成时间为2.

背景

我有一个返回ascii流的硬件&用户可以选择

时间步数 频道数量 一个数据包=[地址][MSB][LSB][校验和]

一个时间戳=[时间分组][CH1分组][CH2分组][CH3分组][CH4分组][CH5分组][CH6分组][CH7分组]

下面是一些精简的代码,我使用这些代码创建7个以上的时间数组,然后通过matplotlib进行绘图。问题是,这需要相当长的时间来处理。。。30000个样本和7个通道2.7秒。我用过cython,我把这个块编译成一个C扩展,速度并没有那么快

完成时间为2.7秒。 禁用校验和为1.8秒此测试为0.9秒 禁用标志扩展为1.8秒。该测试为0.9秒 禁用所有检查的时间为1.0秒

因此,大约有一半的时间是在分割数据 1/4的时间是对每个数据包进行校验和检查 1/4的时间是每个数据包上的签名扩展检查

这些检查非常重要,因为它们有助于识别帧错误w.r.t.USB链路以及测试设备上的任何噪声拾取,因此前4位开始被错误设置

下面的代码是否合理有效,我应该接受它还是真的很糟糕

import numpy as np
import time

BIT_LENGTH=16 # payload bitlength
num_samples=30000 # number of samples
packet = 4 # 4 bytes

chT = b'\x01\x00\x05\xfb' # timestep of 5 @ 1
ch1 = b'\x03\x00\x11\xed' # data 17 @ 3
ch2 = b'\x04\x00\x07\xfc' # data 7 @ 4
ch3 = b'\x08\x00\x17\xe0' # data 23 @ 8
ch4 = b'\x0c\x00e\x96'    # data 101 @ 12
ch5 = b'\x0e\x00\x01\xf0' # data 1 @ 14
ch6 = b'\x13\x04\x00\xe8' # data 1024 @ 19
ch7 = b'\x14\x04\xd2='    # data 1234 @ 20

stream = chT+ch1+ch2+ch3+ch4+ch5+ch6+ch7
stream = stream*num_samples
req = [1,3,4,8,12,14,19,20]  # array of channel addresses.
req_array = [np.zeros(num_samples) for i in req] # init np arrays.


fpga_error_codes = {
        '\x80\x00\x01':'ERR 1', 
        '\x80\x00\x02':'ERR 2', 
        '\x80\x00\x04':'ERR 3', 
        '\x80\x00\x08':'ERR 4', 
        '\x80\x00\x10':'ERR 5', 
        '\x80\x00\x20':'ERR 6', 
        '\x80\x00\x40':'ERR 7',
}

class PacketError(Exception):
    def __init__(self, value):
        self.parameter = value
    def __str__(self):
        return repr(self.parameter)

### FUNCTIONS USED
def checksum(data):
    return (~(data[0] ^ data[1] ^ data[2]) & 0xff).to_bytes(1,byteorder='big',signed=False)


def check_packet_bits(data, s=None, nbits=BIT_LENGTH):
    ''' additional method to assist with error detection'''
    int_data = int.from_bytes(data[1:-1],byteorder='big',signed=True)
    if s=='unsigned':
        if int_data > (2**nbits)-1:
            return True # ERROR!
        else:
            return False
    elif s == 'signed':
        hi = 2**(nbits -1) -1
        lo = -1 * 2**(nbits-1)
        return True if int_data < lo else True if int_data > hi else False
def check_packet(addr, data, num_bits=BIT_LENGTH, sign_type='signed'):
    '''Method to determine whether an ITI packet is valid'''
    if checksum(data[:-1]) != data[-1].to_bytes(1,byteorder='big',signed=False):
        msg = 'Checksum Error: %s' % ( ' '.join([hex(i) for i in data]) )
        raise PacketError(msg)
    elif data[0] == '\x80':
        msg = "%sd      %s" %(fpga_error_codes.get(data[:3],'Unspecified Error'),' '.join([hex(i) for i in data]) )
        raise PacketError(msg)
    elif data[0] != addr:
        msg = "Wrong addr. Got: %d Want: %d      %s" % (data[0],addr,' '.join([hex(i) for i in data]) )
        raise PacketError(msg)
    elif check_packet_bits(data,s=sign_type, nbits=num_bits):
        msg = "Target FPGA sent a corrupted payload addr: %d, page: %d Data: 0x%02x%02x" %(addr, self.present_page,data[1],data[2])
        raise PacketError(msg)
    else:
        return int.from_bytes(data[1:-1],byteorder='big',signed=True)






t0= time.time()
### CODE IN QUESTION 
timestep_iter = zip(*(iter(stream),)*packet*len(req))
for entry,time_window in enumerate(timestep_iter):
    packet_iter = zip(*(iter(bytes(time_window)),)*packet)
    tmp = [check_packet(i,bytes(next(packet_iter)),sign_type=['signed','unsigned'][0],num_bits=12,) for i in req]
    for index,addr in enumerate(req):
        req_array[index][entry] = tmp[index]

req_array[0] = req_array[0].cumsum() - req_array[0]
### CODE IN  QUESTION
print(time.time()-t0)

我猜,这就是使用Python所能得到的。因此,时间可能是合理的。两件事:1/Cython中有几个标志和调整用于禁用某些检查,您是否尝试过设置这些标志和调整?2/您只需使用一次numpy来初始化req_数组,然后在循环中分别为每个元素编制索引。也许有一些地方你可以从第一眼看到更多的numpy风格的代码,看起来不是这样,但也许一些重构可以帮助你。谢谢,我只是想确定我没有犯下一些严重的错误,没有任何理由吃了这个循环。。。我之所以重新考虑这个问题,是因为我将尝试流媒体。每1秒抽取10000个样本100us是一个新块。如果我能在下一个数据包到期之前进行初始处理,应该可以。您可以从itertools将ZIP更改为IZIP。这样,您就不用构建列表,而只需要使用迭代器。这是唯一一件真正吸引我的事。