真正提高性能的最佳方法是摆脱所有样本的 Python 循环,并让 NumPy 在编译的 C 代码中执行此循环。这实现起来有点棘手,但这是可能的。
首先,您需要做一些准备。正如贾斯汀·皮尔(Justin Peel)所指出的,样本的排列模式在一定数量的步骤后会重复。如果 d_1, ..., d_k 是 k 个数据流的除数,b_1, ..., b_k 是流的样本大小(以字节为单位),lcm 是这些除数的最小公倍数,则
N = lcm*sum(b_1/d_1+...+b_k/d_k)
将是流模式之后重复的字节数。如果您已经确定前 N 个字节各自属于哪个流,则可以简单地重复此模式。
您现在可以通过类似于以下内容的方式构建前 N 个字节的流索引数组
stream_index = []
for sample_num in range(lcm):
stream_index += [i for i, ch in enumerate(all_channels)
if ch.samples_for(sample_num)]
repeat_count = [b[i] for i in stream_index]
stream_index = numpy.array(stream_index).repeat(repeat_count)
Here, d
是序列 d_1, ..., d_k 并且b
是序列 b_1, ..., b_k。
现在你可以做
data = numpy.fromfile(my_file, dtype=numpy.uint8).reshape(-1, N)
streams = [data[:,stream_index == i].ravel() for i in range(k)]
您可能需要在末尾填充一点数据以使reshape()
work.
现在,属于每个流的所有字节都位于单独的 NumPy 数组中。您可以通过简单地分配给dtype
每个流的属性。如果您希望第一个流被解释为大端整数,只需编写
streams[0].dtype = ">i"
这不会以任何方式改变数组中的数据,只是改变它的解释方式。
这可能看起来有点神秘,但在性能方面应该要好得多。