Parallele Verarbeitung ohne tiefe Bedeutung in Python

Beim Lösen des Code-Puzzles auf einer bestimmten Site fiel mir überhaupt keine Lösung ein, und ich beschloss, den verbotenen Kreisverkehr auszuprobieren.

Das Problem besteht darin, m zu finden, für das f (m) == c für eine gegebene Funktion f und eine Konstante c ist.

Erstens einfach

Das Ergebnis der Implementierung, ohne vorerst nachzudenken, ist der folgende Code.

solution1


import sys

def solve(m):
    # f,c ist definiert
    return f(m) == c

def solution1():
    limit = int(sys.argv[1])
    ans = [m for m in range(limit) if solve(m)]
    print ans

Ich fragte mich, wie lange die Verarbeitungszeit dauern würde, und bereitete einen Profiler vor.

profile


import cProfile

if __name__ == '__main__':
    profiler = cProfile.Profile()
    profiler.runcall(solution1)
    profiler.print_stats()

Und Renn.

solution1_profile_result


% python mp.py 100000000

(Die Lösung wird weggelassen)

200000003 function calls in 333.009 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
100000000   78.739    0.000  299.934    0.000 mp.py:12(solve)
        1   30.856   30.856  333.009  333.009 mp.py:31(solution1)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
100000000  221.195    0.000  221.195    0.000 {pow}
        1    2.219    2.219    2.219    2.219 {range}

Aufgefächert, parallel und ...

Als ich mich fragte, ob ich die Antwort vorerst wusste, hörte ich eine Stimme von der Seite, die sagte: "Warum parallelisieren Sie nicht www bufefe www?" Während ich denke "Übrigens, ich habe die Parallelverarbeitung von Python noch nie untersucht", werde ich eine parallelisierte Version implementieren.

solution2


import math
import sys
from multiprocessing import Process, Queue


def task(q, num_range):
    #Übergeben von Daten an die Hauptseite über die Warteschlange,Dieses Programm hat keine wesentliche Bedeutung.
    #Mirita Cutter Ducker
    q.put([m for m in num_range if solve(m)])


def solution2():
    queue = Queue()
    limit = int(sys.argv[1])
    worker_num = int(sys.argv[2])
    task_size = int(math.ceil(float(limit) / float(worker_num)))

    #Teilen Sie die zu verarbeitende Liste,Übergeben Sie an jeden Prozess.
    # ref. http://iogi.hatenablog.com/entry/split-list-into-sublist
    num_ranges = izip_longest(*[iter(range(limit))]*task_size)
    processes = [Process(group=None, target=task, args=(queue, num_range))
                 for num_range in num_ranges]

    for process in processes:
        process.start()

    for process in processes:
        print queue.get()
        process.join()

Und die Bearbeitungszeit beträgt fast die Hälfte.

solution2_profile_result


% python mp.py 100000000 4

(Die Lösung wird weggelassen)

1021 function calls (1018 primitive calls) in 182.498 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 __future__.py:48(<module>)
        1    0.000    0.000    0.000    0.000 __future__.py:74(_Feature)
        7    0.000    0.000    0.000    0.000 __future__.py:75(__init__)
        1    0.005    0.005    0.042    0.042 __init__.py:102(Pipe)
        1    0.004    0.004    0.084    0.084 __init__.py:213(Queue)
        1    0.000    0.000    0.000    0.000 connection.py:117(Listener)
        1    0.000    0.000    0.000    0.000 connection.py:183(Pipe)
        1    0.000    0.000    0.000    0.000 connection.py:246(SocketListener)
        1    0.013    0.013    0.037    0.037 connection.py:35(<module>)
        1    0.000    0.000    0.000    0.000 connection.py:426(ConnectionWrapper)
        1    0.000    0.000    0.000    0.000 connection.py:448(XmlListener)
        1    0.000    0.000    0.000    0.000 forking.py:113(Popen)
        4    0.000    0.000    0.027    0.007 forking.py:115(__init__)
       (Abkürzung)

Vorgedächtnis

Die vorherige Implementierung verwendet die Bereichsfunktion, um beim Aufteilen einer Liste eine Liste zu generieren. Daher ist die Speichernutzung großartig.

solution2.png

Dieses Problem wurde gelöst, indem anstelle der Bereichsfunktion die Funktion xrange verwendet wurde. Die Funktion xrange gibt den Iterator anstelle einer Liste zurück, sodass nicht alle gleichzeitig Speicher verbraucht werden.

solution3


import math
import sys
from multiprocessing import Process, Queue


def solution3():
    queue = Queue()
    limit = int(sys.argv[1])
    worker_num = int(sys.argv[2])
    task_size = int(math.ceil(float(limit) / float(worker_num)))

    gen = xrange(limit)
    processes = [Process(
                 group=None,
                 target=task,
                 args=(queue, islice(gen, task_size * i, task_size * (i + 1))))
                 for i in xrange(worker_num)]

    for process in processes:
        process.start()

    for process in processes:
        print queue.get()
        process.join()

Ausführung + Speicherverbrauch zu diesem Zeitpunkt. Die Ausführungszeit hat sich kaum geändert, aber der Speicherverbrauch hat sich dramatisch verringert.

solution3_profile_result


% python mp.py 100000000 4

(Die Lösung wird weggelassen)

1019 function calls (1016 primitive calls) in 187.432 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 __future__.py:48(<module>)
        1    0.000    0.000    0.000    0.000 __future__.py:74(_Feature)
        7    0.000    0.000    0.000    0.000 __future__.py:75(__init__)
        1    0.006    0.006    0.047    0.047 __init__.py:102(Pipe)
        1    0.005    0.005    0.082    0.082 __init__.py:213(Queue)
        1    0.000    0.000    0.000    0.000 connection.py:117(Listener)
        1    0.000    0.000    0.000    0.000 connection.py:183(Pipe)
        1    0.000    0.000    0.000    0.000 connection.py:246(SocketListener)
        1    0.015    0.015    0.041    0.041 connection.py:35(<module>)
        1    0.000    0.000    0.000    0.000 connection.py:426(ConnectionWrapper)
        1    0.000    0.000    0.000    0.000 connection.py:448(XmlListener)
        1    0.000    0.000    0.000    0.000 forking.py:113(Popen)
        4    0.000    0.000    0.001    0.000 forking.py:115(__init__)
       10    0.000    0.000    0.000    0.000 forking.py:130(poll)
        4    0.000    0.000    0.000    0.000 forking.py:146(wait)
        1    0.014    0.014    0.019    0.019 forking.py:35(<module>)
       (Abkürzung)

solution3.png

(Ergänzung) Unterschied der Bereichsfunktion in Python2 / 3

In Python3 gibt die Bereichsfunktion einen Iterator zurück, der als Bereichsklasse bezeichnet wird, sodass die obige Entsprechung nicht erforderlich ist. Vielmehr ist die xrange-Funktion veraltet.

// Python3
% python3
  Python 3.3.0 (default, Mar  2 2013, 11:44:00)
  [GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.24)] on darwin
  Type "help", "copyright", "credits" or "license" for more information.
  >>> a = range(5)
  >>> a
  range(0, 5)
  >>> type(a)
  <class 'range'>
  >>>
  >>> xrange(5)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'xrange' is not defined

// Python2
% python
  Python 2.7.3 (default, May 14 2012, 22:41:33)
  [GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)] on darwin
  Type "help", "copyright", "credits" or "license" for more information.
  >>> a = range(5)
  >>> a
  [0, 1, 2, 3, 4]
  >>> type(a)
  <type 'list'>
  >>>

Recommended Posts

Parallele Verarbeitung ohne tiefe Bedeutung in Python
[Python] Einfache Parallelverarbeitung mit Joblib
Lesen Sie Dateien parallel zu Python
Verarbeiten Sie Bilder in Python ganz einfach mit Pillow
Dateiverarbeitung in Python
So führen Sie eine Mehrkern-Parallelverarbeitung mit Python durch
Multithread-Verarbeitung in Python
Paralleler Download mit Python
Erstellen einer exe-Datei mit Python PyInstaller: PC friert bei paralleler Verarbeitung ein
Verarbeitung in Python beenden
Python: Tiefes Lernen in der Verarbeitung natürlicher Sprache: Grundlagen
Bildverarbeitung mit Python
Erhalten Sie eine Liste der Ergebnisse der Parallelverarbeitung in Python mit Starmap
Parallelverarbeitung mit Mehrfachverarbeitung
Einführung in die verteilte Parallelverarbeitung von Python durch Ray
Bildverarbeitung mit Python (Teil 2)
100 Sprachverarbeitungsklopfen mit Python 2015
UTF8-Textverarbeitung mit Python
Parallelverarbeitung mit lokalen Funktionen
Schaben mit Selen in Python
"Apple-Verarbeitung" mit OpenCV3 + Python3
Betreiben Sie LibreOffice mit Python
Schaben mit Chromedriver in Python
Debuggen mit pdb in Python
Führen Sie Python unittest parallel aus
Akustische Signalverarbeitung mit Python (2)
Umgang mit Sounds in Python
Scraping mit Selen in Python
Asynchrone Verarbeitung (Threading) in Python
Parallele Verarbeitung mit Parallel von Scikit-Learn
Bildverarbeitung mit Python (Teil 1)
Scraping mit Tor in Python
Tweet mit Bild in Python
Kombiniert mit Ordnungszahl in Python
Bildverarbeitung mit Python (3)
Bildverarbeitungssammlung in Python
Verwenden des Python-Modus in der Verarbeitung
[Python] Bildverarbeitung mit Scicit-Image
Zahlenerkennung in Bildern mit Python
Testen mit Zufallszahlen in Python
Python-Parallelverarbeitung (Multiprocessing und Joblib)
GOTO in Python mit erhabenem Text 3
Arbeiten mit LibreOffice in Python: Importieren
100 Sprachverarbeitungsklopfen mit Python (Kapitel 1)
Scraping mit Selen in Python (Basic)
100 Sprachverarbeitung Knock Kapitel 1 in Python
CSS-Analyse mit cssutils in Python
Numer0n mit Elementen, die mit Python erstellt wurden
Öffnen Sie UTF-8 mit Stückliste in Python
100 Sprachverarbeitungsklopfen mit Python (Kapitel 3)
Die Bildverarbeitung mit Python 100 klopft an die Binärisierung Nr. 3
Verwenden Sie rospy mit virtualenv in Python3
Verwenden Sie Python in pyenv mit NeoVim
In Python gibt es keinen Schalter
Beispielcode-Zusammenfassung für die parallele / parallele Python-Verarbeitung
Heatmap mit Dendrogramm in Python + Matplotlib
Passwort für Lehrbuch mit Python generieren
Verwenden Sie OpenCV mit Python 3 in Window
100 Bildverarbeitung mit Python Knock # 2 Graustufen
Bis zum Umgang mit Python in Atom