Python Memory Management: Quick Tips to reduce memory consumption

Python Memory Management: Quick Tips to reduce memory consumption

Python uses lots of memory, especially when running an algorithm over a number of images.

Some algorithms based on Simultaneous Localization and Mapping (SLAM) or Visual SLAM, in which the same algorithm is executed on a sequence of frames. The sequence may consist of more than 1000 frames.

Here are a few tips that will increase python speed and will consume less memory, we have also added graphs as proof of our suggestions.

All the practices to speed up the process were performed on a visual SLAM algorithm for loop closure detection, which uses 2 deep learning models and bag of words dictionary.

After every new image is read, the algorithm checks all previous images for similarity.

 

Tip # 01: Don’t import or create anything inside a loop

Sometimes we need to import or load some models, like pre-trained deep learning models.

Do import all models before loop, you should only code to predict or execute the model inside a loop.

for f in filenames:
    autoencoder = Sequential()

    autoencoder.add(Dense(500, activation='sigmoid', input_shape=(ae_dim,), name='dense_1'))
    autoencoder.add(Dense(100, activation='sigmoid', name='dense_2'))
    autoencoder.add(Dense(500, activation='sigmoid', name='dense_3'))
    autoencoder.add(Dense(ae_dim, activation='sigmoid', name='output'))
    autoencoder.compile(optimizer='adagrad', loss='binary_crossentropy')

Don’t import or create anything inside a loop, if the same thing is used for all iterations, instead load or create the things before the loop, this will create delay or importing anything only once and before starting your actual process.

autoencoder = Sequential()

autoencoder.add(Dense(500, activation='sigmoid', input_shape=(ae_dim,), name='dense_1'))
autoencoder.add(Dense(100, activation='sigmoid', name='dense_2'))
autoencoder.add(Dense(500, activation='sigmoid', name='dense_3'))
autoencoder.add(Dense(ae_dim, activation='sigmoid', name='output'))
autoencoder.compile(optimizer='adagrad', loss='binary_crossentropy')

for f in filenames:
    # your code or execution here
    # results = autoencoder.predict(x)

 

Sometimes, we load a model in the starting section of code but create the model (for deep learning) inside the loop, however same model is used in all iterations.

for f in filenames:
    layer_name = 'dense_layer'
    intermediate_layer_model = Model(inputs=classifier.input, outputs=classifier.get_layer(layer_name).output)
    res2 = intermediate_layer_model.predict(p)

This slows down the system and with every iteration, speed will keep going down as shown in graph below:

Python slow speed

x-axis shows number of frames, while y-axis shows time taken to process single frame (in seconds), the 2000th frame taken around 80 seconds to process one frame, all due to creating the model again and again with every iteration, which was not needed, as we just need to predict results with each frame, so we can just predict (or get results) inside loop, while creating the model before loop. The memory consumption with the above-mentioned practice is 115107.0 KB.

instead, create model after the model is loaded in starting of code, creating the same thing again and again will increase the delay in the process.

classifier = keras.models.load_model(cnn_path)
layer_name = 'dense_layer'
intermediate_layer_model = Model(inputs=classifier.input, outputs=classifier.get_layer(layer_name).output)


for f in filenames:
    res2 = intermediate_layer_model.predict(p)

This puts huge impact on memory consumption and speed. The graph below shows duration taken to process each frame (duration to complete each iteration).

Python memory consumption: faster process

Each frame took less than 1.4 seconds to process and memory consumption was 67485.6 KB. The total time to process all 2000 frames was 23 min 10 seconds.

 

Tip # 02: Delete variable after it is no longer needed

Use del and delete the variable from memory to reduce memory consumption and use gc library and collect garbage at the end of every iteration.

import gc

for f in file_names:
	img = imread(dataset_path + f)

	# Create Patches 
	patches = view_as_windows(img, window_shape, step=window_shape)

	img_dict = []
	patches_considered = 0
	count = 0

        ....

        del img, patches, img_dict, patches_considered, count
        gc.collect()

The graph below shows the effect of deleting variables on the duration of processing each frame:

python faster execution

The maximum time taken by frame is 0.8 seconds. All 2000 frames were processed in 9 min and 23 seconds and total memory consumption was 7977.0 KB.

 

Related Articles:

Leave a Reply

Your email address will not be published.