Python:嵌套for循环是读RLE压缩的3D数据的速度非常慢

2024-10-02 20:30:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要将用游程编码(RLE)压缩的3D数据读入python中的3D numpy数组。在Matlab中,使用嵌套循环大约需要一秒钟的时间。但是在python中这需要48秒!在

这是我的代码:

# Preallocate 3D voxel grid
vox_size = [200,150,200];
voxelGrid3D = np.zeros([200,150,200], dtype=np.uint32);

# Get values from RLE encoded 3D scene: 
# Example:
# 0, (3), 4, (2) --> corresponds to --> 00044 
# --> value == [0, 4]
# --> value_reps == [3, 2]
value = labelsRleCompressed[::2];
value_reps = labelsRleCompressed[1::2];

vox_idx = 0;
vox_idx_all = 0;
num_elements = value_reps.size; # Number of elements to convert
for m in np.arange(0,num_elements):
    numReps = value_reps[m];
    currentValue = value[m];
    for l in np.arange(0,numReps):
    # Compute respective grid indices
        i = (np.floor(vox_idx_all / (vox_size[0] * vox_size[1]) ) % vox_size[2]);
        j = (np.floor(vox_idx_all / (vox_size[0]) ) % vox_size[1]);
        k = (np.floor(vox_idx_all ) % vox_size[0]);

    # Fill grid with label value
        voxelGrid3D[i,j,k] = currentValue;
        vox_idx_all = vox_idx_all + 1;

即使我删除了内部循环并用预先计算的网格索引+重塑函数替换它,整个过程仍然需要10秒!在

^{pr2}$

这对我的申请来说太慢了。有人知道如何让这个更快吗?在


Tags: tosizevaluenpelementsallnumgrid
1条回答
网友
1楼 · 发布于 2024-10-02 20:30:09

加速循环

一开始不要用np.arange公司创建一个迭代器(这将创建一个迭代数组)。使用range(Python3)或xrange(Python2)代替。这会使性能提高百分之几,但这不是真正的瓶颈。在

Matlab有一个实时编译器,可以在循环中执行相当好的性能,CPython在默认情况下没有这个功能。但是有一个实时编译器numbahttp://numba.pydata.org/。在文档中,您将找到可以编译为本机机器代码的受支持函数。在使用numba时,我也建议用循环而不是向量化代码来编写代码,因为这对于编译器来说更容易处理。在

我修改了你的代码。在

def decompress_RLE(labelsRleCompressed,vox_size):
    res=np.empty(vox_size[0]*vox_size[1]*vox_size[2],np.uint32)

    ii=0
    for i in range(0,labelsRleCompressed.size,2):
        value=labelsRleCompressed[i]
        rep=labelsRleCompressed[i+1]
        for j in range(0,rep):
            res[ii]=value
            ii=ii+1

    res=res.reshape((vox_size[0],vox_size[1],vox_size[2]))

    return res

创建基准数据

^{pr2}$

简单地用生成的数据调用函数会导致运行时间7.5秒,这是一个相当糟糕的性能。在

现在让我们用numba。在

import numba
nb_decompress_RLE = numba.jit("uint32[:,:,:](uint32[:],int32[:])",nopython=True)(decompress_RLE) #stick to the datatypes written in the decorator

使用测试数据调用已编译的nb_-decompress_-RLE会在0.0617秒的运行时结果。一个不错的速度提高了119倍!简单地复制数组np.副本速度只有3倍。在

相关问题 更多 >