快速转换大(2.1gb+)二进制文件(纬度/经度/高度到ECEF)

2024-10-04 03:22:31 发布

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

现在,我正在尝试将经纬度高度格式的大量二进制点文件转换为基于文本的ECEF笛卡尔格式(x,y,z)。现在的问题是这个过程非常缓慢。在

我有超过100G的数据要处理,可能会有更多的数据进来。我想让这段代码尽可能快。在

现在我的代码如下所示:

import mmap
import sys
import struct
import time

pointSize = 41

def getArguments():
    if len(sys.argv) != 2:
        print """Not enough arguments.
        example:
            python tllargbin_reader.py input_filename.tllargbin output_filename
        """
        return None
    else:
        return sys.argv

print getArguments()

def read_tllargbin(filename, outputCallback):
    f = open(filename, "r+")
    map = mmap.mmap(f.fileno(),0)
    t = time.clock()
    if (map.size() % pointSize) != 0:
        print "File size not aligned."
        #return
    for i in xrange(0,map.size(),pointSize):
        data_list = struct.unpack('=4d9B',map[i:i+pointSize])
        writeStr = formatString(data_list)
        if i % (41*1000) == 0:
            print "%d/%d points processed" % (i,map.size())
    print "Time elapsed: %f" % (time.clock() - t)
    map.close()


def generate_write_xyz(filename):
    f = open(filename, 'w', 128*1024)
    def write_xyz(writeStr):
        f.write(writeStr)
    return write_xyz

def formatString(data_list):
    return "%f %f %f" % (data_list[1], data_list[2],data_list[3])
args = getArguments()
if args != None:
    read_tllargbin(args[1],generate_write_xyz("out.xyz"))

convertXYZ()基本上是这里的转换公式: http://en.wikipedia.org/wiki/Geodetic_system

我在想,如果用一个线程以~4MB的块读取内容,将它们放入有界缓冲区,使用不同的线程转换为字符串格式,并让最后一个线程将字符串写回另一个硬盘上的文件,这样会不会更快一些。不过,我可能是在冒险。。。在

我现在使用python进行测试,但是如果我能更快地处理这些文件,我不会反对切换。在

有什么建议都很好。谢谢

编辑:

我再次使用cProfile分析了代码,这次将字符串格式和io分开。似乎我真的被字符串格式杀死了。。。这是分析器报告

^{pr2}$

有没有更快的方法来格式化字符串?在


Tags: 字符串importmapdatareturnifdef格式
3条回答

2.1GB的数据读取需要21(@100 MB/s)到70(@30 MB/s)秒。然后,将其格式化并写入可能是其五倍大的数据。这意味着总共13 GB的读写操作需要130-420秒。在

你的抽样显示,阅读需要24秒。因此,写作大约需要两分钟。例如,可以使用SSD来改进读写时间。在

当我转换文件(使用我用C编写的程序)时,我假设转换所需的时间不应超过读取数据本身所需的时间,通常情况下可能要少得多。重叠读写还可以减少I/O时间。因为printf通常太慢,所以我编写自己的自定义格式化例程。在

24秒多少钱?在现代CPU上至少有400亿条指令。这意味着在这段时间内,你可以用至少19条指令来处理每一个数据字节。对于C程序很容易实现,但对于解释性语言(Python、Java、C#、VB)则不行。在

525秒处理(549-24)的剩余时间表明,Python至少要花费8750亿条指令来处理,或者每读取一个字节的数据就要花费415条指令。结果是22比1:解释语言和编译语言之间的比例并不少见。一个构造良好的C程序应该每字节减少大约10条指令。在

为了更精确地解决这个问题,我建议通过将“convertXYZ”设为无操作函数并对结果计时来测量文件读取操作。并测量convert函数,方法是将“read”更改为始终返回一个简单点,但调用转换和输出的次数与实际读取文件的次数相同。(可能还有另一次运行,最终的后转换输出是no-op)根据时间的推移,攻击其中一个可能会更有意义。在

您可以通过将输出写入Python的stdout并让shell执行实际的文件IO,让本地操作系统为您执行一些交错操作。类似地,通过将文件流式传输到stdin(例如,cat oldformat | python conversion.py > outputfile

输入和输出文件在哪种存储上?与Python代码相比,存储特性对性能的影响可能更大。在

更新:考虑到输出速度最慢,并且存储速度很慢,并且在读和写之间共享,请尝试添加一些缓冲区。从the python doc开始,您应该能够通过向os.open调用添加第三个参数来添加一些缓冲区。试试128*1024这样大的吗?在

鉴于formatString是最慢的操作,请尝试以下操作:

def formatString(data_list):
    return " ".join((str(data_list[1]), str(data_list[2]), str(data_list[3])))

相关问题 更多 >