【问题标题】:Python not releasing memory in for loopPython没有在for循环中释放内存
【发布时间】:2019-09-12 03:15:37
【问题描述】:

我正在开发一个函数来对大输入数据进行一些处理。但是,由于我不能一次将所有数据放入内存(点积为 117703x200000 矩阵),我将其分成块并按部分计算。

输出只取前 5 个元素(排序后),因此必须是 117703x5 的形状,这在内存中是可行的。但是,由于某种原因,随着循环的进行,我的内存消耗不断增加,直到出现内存错误。任何想法为什么?代码如下:

def process_predictions_proto(frac=50):
    # Simulate some inputs
    query_embeddings = np.random.random((117703, 512))
    proto_feat = np.random.random((200000, 512))
    gal_cls = np.arange(200000)

    N_val = query_embeddings.shape[0]
    pred = []

    for i in tqdm(range(frac)):
        start = i * int(np.ceil(N_val / frac))
        stop = (i + 1) * int(np.ceil(N_val / frac))
        val_i = query_embeddings[start:stop, :]
        # Compute distances
        dist_i = np.dot(val_i, proto_feat.transpose())
        # Sort
        index_i = np.argsort(dist_i, axis=1)[::-1]
        dist_i = np.take_along_axis(dist_i, index_i, axis=1)
        # Convert distances to class_ids
        pred_i = np.take_along_axis(
            np.repeat(gal_cls[np.newaxis, :], index_i.shape[0], axis=0),
            index_i, axis=1)
        # Use pd.unique to remove copies of the same class_id and
        # get 5 most similar ids
        pred_i = [pd.unique(pi)[:5] for pi in pred_i]
        # Append to list
        pred.append(pred_i)
        # Free memory
        gc.collect()
    pred = np.stack(pred, 0)  # N_val x 5
    return pred

【问题讨论】:

    标签: python numpy memory memory-leaks


    【解决方案1】:

    在调用gc.collect()之前删除所有临时变量,这样数据会立即变成垃圾。

    del start, stop, val_i, dist_i, index_i, dist_i, pred_i
    gc.collect()
    

    在您的代码中,当您第一次调用gc.collect() 时,没有任何数据是垃圾,因为仍然可以从所有变量中引用它。第一次迭代的数据直到第二次迭代结束才被收集;在第一次之后的每次迭代中,您将在内存中有两块数据(当前迭代和上一次迭代)。因此,您使用的内存是所需内存的两倍(我假设某些对象之间存在引用,因此自动 GC 不会清理对象,因为在循环期间会重新分配变量)。

    【讨论】:

    • 那么只需将“gc.collect()”放在循环的开头就足够了吗?
    • 否,因为这样就不会收集上次迭代期间分配的对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 2012-08-13
    • 2017-02-23
    • 2011-11-14
    • 2019-01-27
    • 1970-01-01
    • 2012-10-31
    相关资源
    最近更新 更多