Hướng dẫn python struct unpack performance - hiệu suất giải nén cấu trúc python

Numpy cho phép bạn làm điều này rất nhanh. Trong trường hợp này, tôi nghĩ rằng cách dễ nhất là sử dụng trực tiếp hàm tạo

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
5:

import numpy as np

def with_numpy(buffer):
    # Construct ndarray with: shape, dtype, buffer, offset, strides.
    rotational = np.ndarray((firingBlocks,), '

Điều này trả về các mảng riêng biệt thay vì danh sách lồng nhau, điều này sẽ dễ dàng hơn nhiều để xử lý hơn nữa. Là đầu vào, nó lấy một đối tượng

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
6 (trong Python 2) hoặc bất cứ thứ gì hiển thị giao diện bộ đệm. Thật không may, nó phụ thuộc vào phiên bản Python của bạn (2/3) những đối tượng bạn có thể sử dụng chính xác. Nhưng phương pháp này rất nhanh:

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop

Numpy cho phép bạn làm điều này rất nhanh. Trong trường hợp này, tôi nghĩ rằng cách dễ nhất là sử dụng trực tiếp hàm tạo

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
5:

import numpy as np

def with_numpy(buffer):
   # Construct ndarray with: shape, dtype, buffer, offset, strides.
rotational = np.ndarray((firingBlocks, ), ', buffer, 42 + 2, (100, ))
distance = np.ndarray((firingBlocks, lasers), ', buffer, 42 + 4, (100, 3))
intensity = np.ndarray((firingBlocks, lasers), ', buffer, 42 + 6, (100, 3))
return rotational, distance * 0.002, intensity

Điều này trả về các mảng riêng biệt thay vì danh sách lồng nhau, điều này sẽ dễ dàng hơn nhiều để xử lý hơn nữa. Là đầu vào, nó lấy một đối tượng

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
6 (trong Python 2) hoặc bất cứ thứ gì hiển thị giao diện bộ đệm. Thật không may, nó phụ thuộc vào phiên bản Python của bạn (2/3) những đối tượng bạn có thể sử dụng chính xác. Nhưng phương pháp này rất nhanh:

import numpy as np

firingBlocks = 10 ** 4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks * 100)

   %
   timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop %
   timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop

Biên dịch một

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
9 trước thời hạn, để tránh mã gói Python bằng các phương thức cấp độ mô -đun. Làm điều đó bên ngoài các vòng, vì vậy chi phí xây dựng không được trả nhiều lần.

unpack_ushort = struct.Struct(').unpack
unpack_ushort_byte = struct.Struct(').unpack

Gợi ý: 4

distanceInformation, intensity = unpack_ushort_byte(firingData[startingByte: startingByte + 3])
distanceInformation *= 0.002

Một vài cách để tăng tốc mã Python của bạn, tìm hiểu một vài cách để tăng tốc mã Python của bạn. Xem mã dưới đây.

In[20]: st = struct.Struct(")

In[21]: % timeit struct.unpack(", buf[20: 22])
1.45 µs± 26.5 ns per loop(mean± std.dev.of 7 runs, 1000000 loops each)

In[22]: % timeit st.unpack(buf[20: 22])
778 ns± 10.8 ns per loop(mean± std.dev.of 7 runs, 1000000 loops each)

In[23]: % timeit buf.cast("H")[0]
447 ns± 4.16 ns per loop(mean± std.dev.of 7 runs, 1000000 loops each)

Không sử dụng bất kỳ kỹ thuật nào khác nếu bạn có thể sử dụng danh sách hiểu. Ví dụ: đây là mã để liệt kê tất cả các số từ 1 đến 1000 là hệ số nhân của 3:

laser_iter = struct.iter_unpack(', firingData[firingDataStartingByte + 4])
laser = [
   [d * 0.002, i]
   for d, i in itertools.islice(laser_iter, lasers)
]


Sử dụng danh sách hiểu, nó sẽ là:

Không xác nhận các biến như thế này:

Gợi ý: 5

# I hoped that memory mapping would be the fastest way to access the lookup
# table
with open('evaluators/ranks.dat', 'rb') as ranks_file:
   ranks_data = mmap.mmap(ranks_file.fileno(), 0, prot = mmap.PROT_READ)

def evaluate(cards):
   # Cards are already a list of int to prevent cast
# Preventing method lookup provided the largest speedup so far
read = ranks_data.read
seek = ranks_data.seek
read3 = ranks3_data.read
seek3 = ranks3_data.seek
unpack = struct.unpack

p = 53
# This part of the code is fast enough as I rarely evaluate 3 cards
if len(cards) == 3:
   cards = [int(math.ceil(card / 4)) for card in cards]
cards.sort(reverse = True)

address = ((cards[0] << 8) + (cards[1] << 4) + cards[2]) * 2
seek3(address)
p, = unpack('


Hiểu được sự đánh đổi để đa xử lý và an toàn luồng để viết mã đồng thời, chúng tôi cũng cung cấp một tệp PDF có hình ảnh màu của ảnh chụp màn hình/sơ đồ được sử dụng trong cuốn sách này. Nhấn vào đây để tải xuống.

Bạn cũng có thể lưu một số công việc bằng cách giải nén nhiều giá trị lại với nhau, thay vì một lần:

Numpy cho phép bạn làm điều này rất nhanh. Trong trường hợp này, tôi nghĩ rằng cách dễ nhất là sử dụng trực tiếp hàm tạo

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
5:

import numpy as np

def with_numpy(buffer):
   # Construct ndarray with: shape, dtype, buffer, offset, strides.
rotational = np.ndarray((firingBlocks, ), ', buffer, 42 + 2, (100, ))
distance = np.ndarray((firingBlocks, lasers), ', buffer, 42 + 4, (100, 3))
intensity = np.ndarray((firingBlocks, lasers), ', buffer, 42 + 6, (100, 3))
return rotational, distance * 0.002, intensity

Điều này trả về các mảng riêng biệt thay vì danh sách lồng nhau, điều này sẽ dễ dàng hơn nhiều để xử lý hơn nữa. Là đầu vào, nó lấy một đối tượng

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
6 (trong Python 2) hoặc bất cứ thứ gì hiển thị giao diện bộ đệm. Thật không may, nó phụ thuộc vào phiên bản Python của bạn (2/3) những đối tượng bạn có thể sử dụng chính xác. Nhưng phương pháp này rất nhanh:

import numpy as np

firingBlocks = 10 ** 4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks * 100)

   %
   timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop %
   timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop

Biên dịch một

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
9 trước thời hạn, để tránh mã gói Python bằng các phương thức cấp độ mô -đun. Làm điều đó bên ngoài các vòng, vì vậy chi phí xây dựng không được trả nhiều lần.

unpack_ushort = struct.Struct(').unpack
unpack_ushort_byte = struct.Struct(').unpack


Gợi ý: 4

Một vài cách để tăng tốc mã Python của bạn, tìm hiểu một vài cách để tăng tốc mã Python của bạn. Xem mã dưới đây.

Không sử dụng bất kỳ kỹ thuật nào khác nếu bạn có thể sử dụng danh sách hiểu. Ví dụ: đây là mã để liệt kê tất cả các số từ 1 đến 1000 là hệ số nhân của 3:

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
2

Sử dụng danh sách hiểu, nó sẽ là:

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
3

Không xác nhận các biến như thế này:


Gợi ý: 5

Hiểu được sự đánh đổi để đa xử lý và an toàn luồng để viết mã đồng thời, chúng tôi cũng cung cấp một tệp PDF có hình ảnh màu của ảnh chụp màn hình/sơ đồ được sử dụng trong cuốn sách này. Nhấn vào đây để tải xuống.

import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
4