Source code for pycif.plugins.obsoperators.standard.transforms.utils.clean_memory
import code
import resource
import copy
import sys
from logging import debug
import tracemalloc
import pandas as pd
import numpy as np
from .fetch_inoutputs import fetch_inputs_outputs
from ......utils.datastores.compress import compress_datastore
[docs]
def clean_memory(self, transform_pipe, mapper, period_order,
ddi, transform, direction, mode, only_init):
# if self.monitor_memory:
# current, peak = tracemalloc.get_traced_memory()
# debug(f"Memory usage before cleaning is {current / 1024 ** 2}MB; "
# f"Peak was {peak / 1024 ** 2}MB")
transform_id = (ddi, transform, direction)
# Determine whether the transform outputs are needed
# by future transforms
transf_inout = "inputs" if direction == "adjoint" else "outputs"
neighbout_inout = "outputs" if direction == "adjoint" else "inputs"
pipe_links = self.pipe_links_adj if direction == "adjoint" else self.pipe_links_fwd
transform_ds = transform_pipe.datastore[transform][ddi][transf_inout]
used_outputs = {trid: {d: False for d in transform_ds[trid]}
for trid in transform_ds}
for trf_id in pipe_links[transform_id]:
dd_tmp, trf_tmp, direction_tmp = trf_id
# Check whether successor uses inputs/outputs
for trid in mapper[trf_tmp]["subsimus"][dd_tmp][neighbout_inout]:
if trid not in used_outputs:
continue
for d in mapper[trf_tmp]["subsimus"][dd_tmp][neighbout_inout][trid]:
if d in used_outputs[trid]:
used_outputs[trid][d] = True
# Now loop over the transform datastores and delete those not useful anymore
for trid in transform_pipe.datastore[transform][ddi][transf_inout]:
# Skip if data is further needed after initialization
if mapper[transform][transf_inout][trid].get("keep_data_after_init", False) and only_init:
continue
dates_orig = copy.deepcopy(
list(
transform_pipe.datastore[
transform][ddi][transf_inout][trid].keys()
)
)
for d in dates_orig:
if not used_outputs[trid].get(d, True):
clear_ds = transform_pipe.datastore[
transform][ddi][transf_inout][trid][d]
for tr in clear_ds:
clear_ds[tr] = None
clear_ds[tr] = {}
# Clean memory from the inputs in fwd and outputs in adj
# as they are not used anymore
# Exception with only_init as the input structure might be needed
transf_cleanin = "outputs" if direction == "adjoint" else "inputs"
transf_cleanout = "inputs" if direction == "adjoint" else "outputs"
for trid in transform_pipe.datastore[transform][ddi][transf_cleanin]:
needed_data = any([
mapper[transform][transf_cleanout][trid_in].get(
f"need_{transf_cleanin}", False)
for trid_in in mapper[transform][f'{transf_cleanin}2{transf_cleanout}'][trid]
if trid_in in mapper[transform][transf_cleanout]
])
if needed_data and only_init:
continue
dates_orig = copy.deepcopy(
list(
transform_pipe.datastore[
transform][ddi][transf_cleanin][trid].keys()
)
)
for d in dates_orig:
transform_pipe.datastore[
transform][ddi][transf_cleanin][trid][d] = None
transform_pipe.datastore[
transform][ddi][transf_cleanin][trid][d] = {}
# Now clean memory for past transforms
transform_ind = period_order.index(transform_id)
for trf_id in period_order[:transform_ind]:
if trf_id not in pipe_links:
continue
if transform_id not in pipe_links[trf_id]:
continue
dd_tmp, trf_tmp, direction_tmp = trf_id
# Check that other successors of the neighbours are still used
# Can flush inputs otherwise
if np.all(np.array(
[period_order.index(tr) for tr in pipe_links[trf_id]
if tr in period_order]) <= transform_ind):
neighbour_inout = \
"inputs" if direction_tmp == "adjoint" else "outputs"
ds_in = transform_pipe.datastore[trf_tmp][dd_tmp][neighbour_inout]
for trid in ds_in:
# Skip if data is further needed after initialization
if mapper[trf_tmp][neighbour_inout][trid].get("keep_data_after_init", False) and only_init:
continue
for d in ds_in[trid]:
for tr in ds_in[trid][d]:
ds_in[trid][d][tr] = None
ds_in[trid][d][tr] = {}
# # Force compression of datastores for remaining data
# for inout in ["inputs", "outputs"]:
# for trid_in in transform_pipe.datastore[transform][ddi][inout]:
# inoutputs = transform_pipe.datastore[transform][ddi][inout][trid_in]
# for d in inoutputs:
# if not isinstance(inoutputs[d], pd.DataFrame):
# continue
# inoutputs[d] = compress_datastore(inoutputs[d])
# if self.monitor_memory:
# current, peak = tracemalloc.get_traced_memory()
# debug(f"Memory usage after cleaning is {current / 1024 ** 2}MB; "
# f"Peak was {peak / 1024 ** 2}MB")
# for tr in transform_pipe.datastore:
# print(tr)
# print(transform_pipe.datastore[tr])
# print()
# print(__file__)
# import code
# code.interact(local=dict(locals(), **globals()))
return transform_pipe
# transform_direction = "adjoint" if mode == "adj" else "forward"
# transform_id = (ddi, transform, transform_direction)
# transform_id = (ddi, transform, direction)
# # Determine whether the transform outputs are needed
# # by future transforms
# transf_inout = "inputs" if mode == "adj" else "outputs"
# neighbout_inout = "outputs" if mode == "adj" else "inputs"
# pipe_links = self.pipe_links_adj if mode == "adj" else self.pipe_links_fwd
# transform_ds = transform_pipe.datastore[transform][ddi][transf_inout]
# used_outputs = {trid: {d: False for d in transform_ds[trid]}
# for trid in transform_ds}
# print(__file__)
# import code
# code.interact(local=dict(locals(), **globals()))
# for trf_id in pipe_links[transform_id]:
# dd_tmp, trf_tmp, direction_tmp = trf_id
# # Check whether successor uses inputs/outputs
# for trid in mapper[trf_tmp]["subsimus"][dd_tmp][neighbout_inout]:
# if trid not in used_outputs:
# continue
# for d in mapper[trf_tmp]["subsimus"][dd_tmp][neighbout_inout][trid]:
# if d in used_outputs[trid]:
# used_outputs[trid][d] = True
# # Now loop over the transform datastores and delete those not useful anymore
# for trid in transform_pipe.datastore[transform][ddi][transf_inout]:
# dates_orig = copy.deepcopy(
# list(
# transform_pipe.datastore[
# transform][ddi][transf_inout][trid].keys()
# )
# )
# for d in dates_orig:
# if not used_outputs[trid].get(d, True):
# clear_ds = transform_pipe.datastore[
# transform][ddi][transf_inout][trid][d]
# for tr in clear_ds:
# clear_ds[tr] = None
# clear_ds[tr] = {}
# # Clean memory from the inputs in fwd and outputs in adj
# # as they are not used anymore
# transf_cleanin = "outputs" if mode == "adj" else "inputs"
# for trid in transform_pipe.datastore[transform][ddi][transf_cleanin]:
# dates_orig = copy.deepcopy(
# list(
# transform_pipe.datastore[
# transform][ddi][transf_cleanin][trid].keys()
# )
# )
# for d in dates_orig:
# transform_pipe.datastore[
# transform][ddi][transf_cleanin][trid][d] = None
# transform_pipe.datastore[
# transform][ddi][transf_cleanin][trid][d] = {}
# # Now clean memory for past transforms
# transform_ind = period_order.index(transform_id)
# for trf_id in period_order[:transform_ind]:
# if trf_id not in pipe_links:
# continue
# if transform_id not in pipe_links[trf_id]:
# continue
# dd_tmp, trf_tmp, direction_tmp = trf_id
# # Check that other successors of the neighbours are still used
# # can flush inputs otherwise
# if np.all(np.array(
# [period_order.index(tr) for tr in pipe_links[trf_id]
# if tr in period_order]) <= transform_ind):
# neighbour_inout = \
# "inputs" if direction_tmp == "adjoint" else "outputs"
# ds_in = transform_pipe.datastore[trf_tmp][dd_tmp][neighbour_inout]
# for trid in ds_in:
# for d in ds_in[trid]:
# for tr in ds_in[trid][d]:
# ds_in[trid][d][tr] = None
# ds_in[trid][d][tr] = {}
# return transform_pipe