加载np数组非常慢

时间:2012-08-28 05:32:24

标签: numpy python-2.7

python的新手(很酷),第一个问题。我正在读取50+ mb的ascii文件,扫描属性标记并将数据解析为numpy数组。我在整个循环中放置了时序报告,并使用np.append()找到了罪魁祸首,while循环。想知道是否有更快的方法。

这是一个示例输入文件格式,包含用于调试的伪数据:

... 标签参数 char名字“Poro” 数组浮点数据100
   1 2 3 4 5 6 7 8 9 10 11 12    13 14 15 16 17 18 19 20 21 22 23 24    25 26 27 28 29 30 31 32 33 34 35 36    37 38 39 40 41 42 43 44 45 46 47 48    49 50 51 52 53 54 55 56 56 58 59 60    61 62 63 64 65 66 67 68 69 70 71 72    73 74 75 76 77 78 79 80 81 82 83 84    85 86 87 88 89 90 91 92 93 94 95 96    97 98 99 100 ENDTAG ...

这是代码片段,对于350k元素数组,while循环需要70秒:

def readParameter(self, parameterName):
    startTime = time.time()
    intervalTime = time.time()
    token = "tag parameter"
    self.inputBuffer.seek(0)
    for lineno, line in enumerate(self.inputBuffer, 1):
        if token in line:
            line = self.inputBuffer.next().replace('"', '').split()
            elapsedTime = time.time() - intervalTime
            logging.debug("    Time to readParameter find token: " + str(elapsedTime))
            intervalTime = time.time()
            if line[2] == parameterName:
                line = self.inputBuffer.next()
                line = self.inputBuffer.next()
                np.parameterArray = np.fromstring(line, dtype=float, sep=" ")
                line = self.inputBuffer.next()

                **while not "endtag" in line:
                    np.parameterArray = np.append(np.parameterArray, np.fromstring(line, dtype=float, sep=" "))
                    line = self.inputBuffer.next()**

                elapsedTime = time.time() - startTime
                logging.debug("    Time to readParameter load array: " + str(elapsedTime))
                break
    elapsedTime = time.time() - startTime
    logging.debug("    Time to readParameter: " + str(elapsedTime))
    logging.debug(np.parameterArray)
    np.parameterArray = self.make3D(np.parameterArray)
    return np.parameterArray

谢谢,杰夫

1 个答案:

答案 0 :(得分:4)

附加到数组需要调整数组的大小,这通常需要分配一个新的内存块,该内存块足以容纳新数组,将现有数组复制到新位置,并释放它以前使用的内存。所有这些操作都很昂贵,而且你正在为每个元素做这些操作。使用350k元素,它基本上是垃圾收集器内存碎片压力测试。

预分配您的阵列。你有了count参数,所以创建一个大小的数组,并在你的循环中,只需将新解析的元素分配给数组中的下一个位置,而不是附加它。你必须保留自己的计数器来填充多少元素。 (您可以迭代遍历空白数组的元素并替换它们,但这会使错误处理更难以添加。)