加快将二进制文件中的numpy数据写入文件。层发电机

时间:2017-07-06 17:02:49

标签: python numpy mesh

我制作了自己的合作出口商,即使它正在运作,也很慢。我假设问题来自于专门针对元素进行循环,并且基于this comment来自使用data.enrichedData.findAll{it.@datatable == "ROUTING"}.customer.each { println it.text() }

导出struct.pack的挑战在于它是元组的一维向量。导出Nodes的挑战是Faces的每一行前面都有一个数字" 3"以int格式。

我将整个代码放在这里,因为它可以作为MWE,也可以作为参考,如果有人想使用代码以层格式导出网格。

代码:

uchar

结果:

from __future__ import division
import numpy as np
import struct
import timeit

def Timeme(funct,var,NN=10,NNN=10):
    for i in xrange(NN):
        start =timeit.default_timer()
        for t in xrange(NNN):
            funct(*var)
        end =timeit.default_timer()
        print str(i)+': '+str((end - start)/NNN*1000)  

# This function is fictitious. In reality the 
# Nodes array is imported from another module
def MakeNodes(Nr,Nc):
    Nodes=np.zeros(Nr*Nc,dtype=[('x', np.float32), ('y', np.float32), ('z', np.float32)])
    x = np.linspace(0, (Nc-1), Nc, dtype=np.float32)
    y = np.linspace((Nr-1),0 , Nr, dtype=np.float32)
    xv, yv = np.meshgrid(x, y, sparse=False, indexing='xy')
    Nodes['x']=xv.flatten()
    Nodes['y']=yv.flatten()
    Nodes['z']=(1/2-((Nodes['x']/Nc-1/2)**2+ (Nodes['y']/Nr-1/2)**2))*Nr/2
    return Nodes

# Function below explained in https://stackoverflow.com/questions/44934631
def MakeFaces(Nr,Nc):
    out = np.empty((Nr-1,Nc-1,2,3),dtype=int)
    r = np.arange(Nr*Nc).reshape(Nr,Nc)
    l1=r[:-1,:-1]
    l2=r[:-1,1:]
    l3=r[1:,:-1]
    l4=r[1:,1:]
    out[:,:, 0,0] = l2
    out[:,:, 0,1] = l1
    out[:,:, 0,2] = l3
    out[:,:, 1,0] = l4
    out[:,:, 1,1] = l2
    out[:,:, 1,2] = l3
    out.shape =(-1,3)
    return out

def ExportPlyBinary(Nodes,Faces,file):
    LN=len(Nodes)
    LF=len(Faces)

    header= \
    "ply\n" \
    "format binary_little_endian 1.0\n" \
    "element vertex "+str(LN)+"\n" \
    "property float x\n" \
    "property float y\n" \
    "property float z\n" \
    "element face "+str(LF)+"\n" \
    "property list uchar int vertex_indices\n" \
    "end_header\n"

    with open(file, 'wb') as fp:
        fp.write(header)
        s = struct.Struct('<fff')
        for nd in Nodes:
            fp.write(s.pack(nd['x'],nd['y'],nd['z']))

        s = struct.Struct('<Blll')
        for fc in Faces:
            fp.write(s.pack(3,fc[0],fc[1],fc[2]))

Nr=200
Nc=200
Nodes=MakeNodes(Nr,Nc)
Faces=MakeFaces(Nr,Nc)
Timeme(ExportPlyBinary,(Nodes,Faces,"Test.ply"))
Timeme(np.savez,("Test_np.ply", Nodes,Faces))

2 个答案:

答案 0 :(得分:1)

为什么不使用可用的东西?

例如trimesh? https://pypi.python.org/pypi/trimesh

即使您不只是包的一小部分,您也可以从源代码中复制和调整此部分。 (当然提到作者)

答案 1 :(得分:0)

我按照@ max9111的建议检查了Trimesh,并且能够创建更高效​​的功能。关键思想(在我的理解中)是(1)通过创建新数组转换为正确的数据类型和顺序,以及(2)使用.tostring函数。我最初避开了这个方向,因为它似乎浪费了记忆,但在这一点上,优势很明显。请注意,我的Nodes数组已准备好应用.tostring,但我会保持解决方案更加通用。

def NewExportPlyBinary(Nodes,Faces,file):
    LN=len(Nodes)
    LF=len(Faces)

    header= \
    "ply\n" \
    "format binary_little_endian 1.0\n" \
    "element vertex "+str(LN)+"\n" \
    "property float x\n" \
    "property float y\n" \
    "property float z\n" \
    "element face "+str(LF)+"\n" \
    "property list uchar int vertex_indices\n" \
    "end_header\n"

    dtype_vertex = [('vertex', '<f4', (3))]
    vertex = np.empty(LN, dtype=dtype_vertex)
    vertex['vertex']=np.stack((Nodes['x'],Nodes['y'],Nodes['z']),axis=-1)

    # vertex=Nodes

    dtype_face = [('count', '<u1'),('index', '<i4', (3))]
    faces = np.empty(LF, dtype=dtype_face)
    faces['count'] = 3
    faces['index'] = Faces

    with open(file, 'wb') as fp:
        fp.write(header)
        fp.write(vertex.tostring())
        fp.write(faces.tostring())

我现在为200x200示例获得以下时间:

0: 373.361611377 # original ExportPlyBinary
0: 20.5686725792 # numpy's savez
0: 4.85469689001 # NewExportPlyBinary

注意:当问题规模增加时,savezNewExportPlyBinary之间的差异基本消失。