Python Многопроцессорность делает систему не отвечает - PullRequest
0 голосов
/ 28 февраля 2020

Я обрабатываю несколько наборов данных (которые инкапсулированы с пользовательским объектом python и сериализованы на диске) с кучей операций, которые занимают около 10/15 секунд для каждого. Я приложил эти операции к процессу и вызываю 160 процессов для планирования.

Я установил Semaphore(6), поскольку у меня 8-ядерный процессор.

Проблема заключается в том, что процесс 80 , ОЗУ переполняется, Своп также полон, а система полностью не отвечает.

Я также попытался использовать сборщик мусора, но это не имело никакого значения.

Он начинает работать нормально, и когда время проходит, система полностью зависает. Вот скриншот htop прямо перед cra sh: Размер свопа составляет 5 ГБ, но он достигает 8 ГБ, прежде чем cra sh

Моя система: - Ubuntu 18.04 LTS - i7 2600 4 ядра (8 потоков) - GTX 1060 3 ГБ - Ram DDR3 8 ГБ

Вот код:

import multiprocessing as mp
import sys
import time
from pathlib import Path

import gc


def main():
    all_args_list = load_datasets()

    processes = []
    queue_res = mp.Queue()
    cpu_lim = mp.Semaphore(mp.cpu_count() - 2) # Use 6 of my 8 cores

    for i, some_args in enumerate(all_args_list):

        p = mp.Process(target=process_routine, args=(some_args, queue_res, cpu_lim))
        processes.append(p)

    for process in processes:
        process.start()

    for process in processes:
        process.join()

    results = [queue_res.get() for p in processes]

    save(results)


def process_routine(some_args, queue_obj, cpu_lim):
    cpu_lim.acquire()

    # Do my operations ....
    process_result_dict = my_operations(some_args)

    # Save process result
    res_obj.put(process_result_dict)

    gc.collect()
    cpu_lim.release()


if __name__ == '__main__':
    main()

Как мне поступить, чтобы python не перехватил все Память? Почему использование ОЗУ увеличивается со временем? Разве сборщик мусора не собирает старые объекты?

Спасибо за ваше время!

РЕДАКТИРОВАТЬ

Я изменил несколько процессов на Пул. Проблема в том, что теперь он запускает каждый процесс только индивидуально, используя apply_async() или apply():

pool = mp.Pool(processes=mp.cpu_count())
results = [pool.apply_async(process_routine, args=(my_args,)) for id, my_args in enumerate(datasets)]

1 Ответ

0 голосов
/ 28 февраля 2020

Вместо того, чтобы запускать 160 процессов, вы должны попытаться использовать пул с размером, равным количеству процессоров в вашей системе, в качестве отправной точки. Взгляните на ProcessPoolExecutor . Нет необходимости создавать свои собственные логики семафора c, когда это может управлять пулом / ресурсами процесса для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...