Как я могу достичь 100% загрузки процессора при использовании многопроцессорной обработки? - PullRequest
1 голос
/ 02 марта 2020

Я пытаюсь ускорить мой python3 сценарий, используя мультиобработку, запустив 4 процесса одновременно. Тем не менее, мои процессы никогда не достигают 100% загрузки процессора. Ядро моего кода просто читает запись .mp3 и выполняет некоторое распознавание с помощью scikit-learn, а затем сохраняет результаты в .json.

, вот мой вывод top:

top - 17:07:07 up 18 days,  3:31,  4 users,  load average: 3.73, 3.67, 3.87
Tasks: 137 total,   1 running,  75 sleeping,  18 stopped,   0 zombie
%Cpu(s): 32.8 us, 20.3 sy,  0.0 ni, 46.3 id,  0.0 wa,  0.0 hi,  0.5 si,  0.1 st
KiB Mem :  8167880 total,  2683088 free,  4314756 used,  1170036 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  3564064 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                           
 5832 am        20   0 1887644 776736  24076 S  63.0  9.5 201:10.19 python3                                                           
 5829 am        20   0 1956336 845556  24348 S  55.0 10.4 200:31.20 python3                                                           
 5830 am        20   0 2000772 890260  23820 S  55.0 10.9 200:39.80 python3                                                           
 5834 am        20   0 2430932 1.260g  24252 S  50.3 16.2 200:45.52 python3                                                           
 4657 am        20   0  108116   4460   3424 S   0.3  0.1   1:11.48 sshd                                                              
 6564 root      20   0       0      0      0 I   0.3  0.0   7:30.08 kworker/2:1                                                       
    1 root      20   0  225212   6660   4452 S   0.0  0.1   0:26.33 systemd                                                           
......

Как вы можете видеть в предыдущем выводе, нет большой нагрузки на память, поэтому ограниченное использование ЦП не может быть связано с вводом / выводом или памятью.

Есть ли в любом случае 'заставить' python использовать все 100%? или как я могу отладить свой код, чтобы выяснить, что вызывает это? и если я упускаю что-то очевидное, как я могу изменить свой код для достижения 100% загрузки ЦП?

Вот небольшой обзор моего основного кода многопроцессорной обработки:

# -*- coding: utf-8 -*-
import os
import time
import logging
import cProfile
import multiprocessing as mp
from packages.Recognizer import Recognizer
from packages.RecordingFile import RecordingFile
from packages.utils.pickle_utils import pickle_load

_PRINTS = True


class ServerSER:

    def __init__(self, date, model_fname, results_path,
                 nprocs=1, run_type="server"):
       # bunch of inits


    def process_files(self):
        # Setup a list of processes that we want to run
        self.processes = [mp.Process(target=self.recognition_func, args=("processes/p" + str(p),
                                     self.model_obj, p, self.output))
                          for p in range(self.nprocs)]
        # Run processes
        for p in self.processes: p.start()

        # Exit the completed processes
        for p in self.processes: p.join()

        # Get process results from the output queue
        self.results = []
        for p in self.processes:
            try:
                r = self.output.get_nowait()
                self.results.append(r)
            except Exception as e:
                print(e)

        return [e[1][0] for e in self.results]


    def recognition_func(self, pfolder, model_obj, pos, output, profile=True):
        # start profiling
        pr = cProfile.Profile()
        pr.enable()

        # start logging
        logger_name = "my-logger" + str(pos)
        logging.basicConfig(format='%(asctime)s  %(levelname)5s  %(message)s',
                            level=logging.INFO, filename=logger_name + ".txt")
        logging.info("Start logging for process number " + str(pos))

        # start processing until no files available
        while len([f for f in os.listdir(pfolder) if ".mp3" in f]) > 0: 
            # get oldest file
            oldest_file = [f for f in self.sorted_ls(pfolder) if ".mp3" in f][0]

            # process
            try: 
                recording = RecordingFile(pfolder=pfolder,
                                          base_url=self.base_url,
                                          fpath=oldest_file,
                                          results_path=self.results_path)

                if _PRINTS:
                    msg = "%10s : %50s" % ("PROCESSING", oldest_file)
                    logging.info(msg)

                    # prints
                    print("------------------------------------------------------------------------")
                    print("%10s : %50s" % ("PROCESSING", oldest_file))
                    print("------------------------------------------------------------------------")

                # recognize for file
                _ = Recognizer(recording=recording,
                               duration_step=1,
                               channel=1,
                               model_obj=self.model_obj)

                # clean ups
                recording.delete_files()
                print("%10s." % ("DONE"))
                print("------------------------------------------------------------------------")

            except Exception as e:
                self.errors[oldest_file] = e
                logging.warn(e)
                print(e, " while processing ", oldest_file)

        # put results in queue
        self.output.put((pos, [self.errors, self.durations]))

        # save profiling results
        # pr.print_stats(sort='time')
        pr.disable()
        pr.dump_stats("incode_cprofiler_output" + str(pos) + ".txt")
        return True

вывод uname -a: Linux 4.15.0-70-generic #79-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux
вывод lscpu:

Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
Byte Order:          Little Endian
CPU(s):              4
On-line CPU(s) list: 0-3
Thread(s) per core:  1
Core(s) per socket:  4
Socket(s):           1
NUMA node(s):        1
Vendor ID:           GenuineIntel
CPU family:          6
Model:               94
Model name:          Intel Core Processor (Skylake, IBRS)
Stepping:            3
CPU MHz:             3696.000
BogoMIPS:            7392.00
Virtualization:      VT-x
Hypervisor vendor:   KVM
Virtualization type: full
L1d cache:           32K
L1i cache:           32K
L2 cache:            4096K
L3 cache:            16384K
NUMA node0 CPU(s):   0-3

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

При воспроизведении бита с количеством процессов происходит следующее:

  • В случае использования одного процесса загрузка ЦП составляет 110%.
  • Для двух процессов загрузка ЦП составляет 80%.
  • При 6 процессах каждый процесс занимает около 50% загрузки ЦП.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...