0

I have a binary file and I am parsing it to a numpy array in Python like the following:

bytestream= np.fromfile(path, dtype=np.int16)

 for a in range(sizeA):
        for x in range(0, sizeX):
            for y in range(0, sizeY):
                for z in range(0, sizeZ):
                    parsed[a, x, y, z] = bytestream[z + (sizeZ * x) + (sizeZ * sizeX * y) + (sizeZ * sizeX * sizeY * a)]

However, this is very very slow. Can anyone tell me why and how to speed it up?

4

2 回答 2

1

(sizeZ * x) + (sizeZ * sizeX * y)你似乎在你的代码中犯了一个错误,我相信 x 和 y 在假设行主要排序时应该颠倒过来。无论如何,请检查下面的代码,它可以验证 reshape 是您想要的。它慢的原因是嵌套的 for 循环。

在 python 中,for 循环是一个非常复杂的结构,开销非常大。因此,在大多数情况下,您应该避免使用 for 循环并使用库提供的函数(也有 for 循环,但在 c/c++ 中完成)。您会发现“删除 for 循环”是 numpy 中的一个常见问题,因为大多数人会首先以最直接的方式尝试一些他们知道的算法(例如卷积,最大池化)。并意识到它非常慢,并寻找基于 numpy api 的巧妙替代方案,其中大部分计算转移到 c++ 端而不是在 python 中发生。

import numpy as np

# gen some data 
arr= (np.random.random((4,4,4,4))*10).astype(np.int16)
arr.tofile('test.bin')

# original code
bytestream=np.fromfile('test.bin',dtype=np.int16)
parsed=np.zeros(arr.shape,dtype=np.int16)
sizeA,sizeX,sizeY,sizeZ=arr.shape
for a in range(sizeA):
    for x in range(0, sizeX):
        for y in range(0, sizeY):
            for z in range(0, sizeZ):
                parsed[a, x, y, z] = bytestream[z + (sizeZ * y) + (sizeZ * sizeX * x) + (sizeZ * sizeX * sizeY * a)]

print(np.allclose(arr,parsed))
print(np.allclose(arr,bytestream.reshape((sizeA,sizeX,sizeY,sizeZ))))
于 2017-11-21T10:14:40.977 回答
0

您正在parsed逐个单元格地更新 numpy 数组,必须在 python 和每个单元格的 numpy 的 C 实现之间反弹。这是一个严重的开销。(更不用说必须像 zaw lin 所说的那样在每次 python 迭代中更新 python 变量的a成本或计算索引的成本)yxz

当您执行一些 numpy C 代码时,使用numpy.copynumpy.reshapenumpy.moveaxisnumpy 在一批中更新尽可能多的值。

于 2017-11-22T09:15:27.927 回答