为什么我们在这里需要字节序?

11

我正在阅读一个源代码,它会下载zip文件并将数据读入到numpy数组中。这段代码应该能在macOS和Linux上正常运行,以下是我看到的代码片段:

def _read32(bytestream):
    dt = numpy.dtype(numpy.uint32).newbyteorder('>')
    return numpy.frombuffer(bytestream.read(4), dtype=dt)

这个函数在以下情境中被使用:

with gzip.open(filename) as bytestream:
    magic = _read32(bytestream)

很容易看出这里发生了什么,但我对 newbyteorder('>') 的目的感到困惑。我阅读了文档,知道了字节顺序的含义,但无法理解为什么开发者要添加 newbyteorder(在我看来它并不是真正需要的)。

2个回答

8

这是因为下载的数据以大端格式存储,如源页面所述:http://yann.lecun.com/exdb/mnist/

文件中的所有整数都以高位字节优先(大端)格式存储,这是大多数非英特尔处理器使用的格式。使用英特尔处理器和其他低端机器的用户必须翻转标题的字节。


如果您查看第45行的代码,您会看到 data = numpy.frombuffer(buf, dtype=numpy.uint8),这让事情有点混乱。为什么在这行代码中没有指定字节序? - emanuele
1
因为数据类型 uint8 只有 1 个字节长,字节序仅在多字节数据类型中才有意义。 - HeyYO

4

这只是一种确保从生成的数组中按照正确顺序解释字节的方式,而不考虑系统本地的字节顺序。

默认情况下,内置的NumPy整数数据类型将使用与您的系统本地相同的字节顺序。例如,我的系统是小端字节序,因此仅使用dtype numpy.dtype(numpy.uint32) 就意味着从字节顺序为大端字节序的缓冲区读取到数组的值将无法被正确解释。

如果np.frombuffer要接收已知处于特定字节顺序的字节,则最佳做法是使用newbyteorder修改dtype。在 np.frombuffer的文档中提到了这一点:

Notes

If the buffer has data that is not in machine byte-order, this should be specified as part of the data-type, e.g.:

>>> dt = np.dtype(int)
>>> dt = dt.newbyteorder('>')
>>> np.frombuffer(buf, dtype=dt)

The data of the resulting array will not be byteswapped, but will be interpreted correctly.


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